From 19637be7fa636592f96db2af7ea14791a710197b Mon Sep 17 00:00:00 2001 From: Theodore Cipicchio Date: Tue, 16 Apr 2019 17:43:33 -0700 Subject: [PATCH] Fix 64-bit Windows compatibility Py_BuildValue() expects Py_ssize_t values for buffer lengths provided for "y#" and similar format specifiers. The PUBLICKEYBYTES and SECRETKEYBYTES constants passed to Py_BuildValue() in ed25519_publickey() are treated as 32-bit int values by default, so they must be cast to Py_ssize_t to work correctly on 64-bit architectures, as Py_ssize_t is 64 bits on such targets. For x86-64 targets, this was only causing issues on Windows, as the Microsoft x64 calling convention only uses four registers for argument passing instead of the six used by the System V AMD64 ABI (Linux, macOS, etc.). 32-bit values are automatically zero-extended to 64-bits when loaded into a register, so the size arguments get promoted to 64-bits automatically if they can be passed in a register. The SECRETKEYBYTES argument, being the fifth argument to Py_BuildValue(), gets passed on the stack on Windows, so the upper 32-bits of the value read for that argument are pulled from whatever is in memory adjacent to the value in the stack, often leading to a MemoryError being raised as Py_BuildValue() attempts to allocate a large amount of memory for the "signkey" bytes object. --- src/ed25519-glue/ed25519module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ed25519-glue/ed25519module.c b/src/ed25519-glue/ed25519module.c index f7faaf3..fbfe1f5 100644 --- a/src/ed25519-glue/ed25519module.c +++ b/src/ed25519-glue/ed25519module.c @@ -54,8 +54,8 @@ ed25519_publickey(PyObject *self, PyObject *args) return NULL; crypto_sign_publickey(verfkey, signkey, seed); return Py_BuildValue("("y"#"y"#)", - verfkey, PUBLICKEYBYTES, - signkey, SECRETKEYBYTES); + verfkey, (Py_ssize_t)PUBLICKEYBYTES, + signkey, (Py_ssize_t)SECRETKEYBYTES); } PyDoc_STRVAR(ed25519_sign_doc,