Repository navigation
Fix 64-bit Windows compatibility - #14
Merged
Merged
Conversation
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.
Contributor
Author
|
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). |
Open
|
When merge? |
Owner
|
Wow, good catch and great analysis. The patch looks good, I'll land it shortly. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.