warner / python-ed25519

Python bindings to the Ed25519 public-key signature system
Other
164 stars 38 forks source link

Fix 64-bit Windows compatibility #14

Closed okready closed 5 years ago

okready commented 5 years ago

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.

okready commented 5 years ago

I believe this fixes #12 (some comments mentioned the issue went away after downgrading to various Python versions, but I don't know whether that included switching from 64-bit to 32-bit versions of Python).

hclivess commented 5 years ago

When merge?

warner commented 5 years ago

Wow, good catch and great analysis. The patch looks good, I'll land it shortly.