-
Notifications
You must be signed in to change notification settings - Fork 351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix differing behavior in C implementation on big-endian platforms #118
Fix differing behavior in C implementation on big-endian platforms #118
Conversation
This change only appeared to fix the problem seen with big-endian platforms because of a misconfiguration on my part, it seems. |
Is the bug still there and this fix was bad, or was there no bug to begin with? |
The fix was bad. |
@sneves What about the
If it looks like the problem exists and this change is the right way to fix it, I will clean up the change so that it does not violate strict aliasing rules, ask @jakub-zwolakowski to check my work, and re-open this PR. |
The above appears to fix a problem for plaintexts of length 1025 but something continues to be wrong for plaintexts of length 2048. |
EDIT: Oh ignore this comment, I'm confused and talking about the Rust implementation. I tried to get the C implementation running under I haven't looked closely at the proposed fix yet, but here's an important data point: We do big endian emulation as part of our CI testing, using
As a sanity check, I've pushed a branch that intentionally breaks big endian. Here's the CI run: https://github.com/BLAKE3-team/BLAKE3/runs/1182629230. As expected, only the emulated I guess the first thing I should ask is whether we're testing the same cases. I think |
Ok, now that I understand what's going on, I was able to hack together
|
@oconnor663 I am impressed that cross allows you to reproduce this problem that lies in the C code (when executed on a big-endian machine). One possible next step is to check if the |
@pascal-cuoq I had the exact same experience you did. Fixing the bug at 1025 exposed another bug at 2048. I've pushed a branch that fixes both: https://github.com/BLAKE3-team/BLAKE3/tree/fix_big_endian. If you get a chance, could you see if that commit works for you? |
And thanks a million for catching this issue! I will definitely get our C code under |
For some context as to why these failures appeared at the lengths where they did:
|
I will accept the thanks on behalf of @jakub-zwolakowski who did all the work. TrustInSoft CI has now checked that your branch https://github.com/BLAKE3-team/BLAKE3/tree/fix_big_endian makes the 32-bit and 64-bit big-endian results of the C implementation consistent with the little-endian results for the following input sizes:
After that branch of yours is merged, @jakub-zwolakowski will submit a PR to show what the configuration files for TrustInSoft CI looks like for these four architectures. It is complementary with cross, and we hope that you will find it useful: it can only check the pure C implementation (with the implementation-defined parameters of GCC targeting x86/x86-64/ppc32/ppc64) but it detects all the C Undefined Behaviors that ASan/UBSan/MSan detect and more. |
Kudos to @pascal-cuoq and @jakub-zwolakowski from TrustInSoft for catching these bugs. Original report: #118
I just put up #119 with those fixes and expanded CI coverage for this case. I'll merge it as soon as CI passes. |
#119 is now merged. |
Changes since 0.3.6: - BUGFIX: The C implementation was incorrect on big endian systems for inputs longer than 1024 bytes. This bug affected all previous versions of the C implementation. Little endian platforms like x86 were unaffected. The Rust implementation was also unaffected. @jakub-zwolakowski and @pascal-cuoq from TrustInSoft reported this bug: #118 - BUGFIX: The C build on x86-64 was producing binaries with an executable stack. @tristanheaven reported this bug: #109 - @mkrupcale added optimized implementations for SSE2. This improves performance on older x86 processors that don't support SSE4.1. - The C implementation now exposes the `blake3_hasher_init_derive_key_raw` function, to make it easier to implement language bindings. Added by @k0001.
Kudos to @pascal-cuoq and @jakub-zwolakowski from TrustInSoft for catching these bugs. Original report: BLAKE3-team#118
Hello,
J-P did not express much interest for “exotic” platforms, so @jakub-zwolakowski only configured the C implementation to be interpreted on a 32-bit big-endian and on a 64-bit big-endian platform, in addition to x86 and x86-64. The chosen platforms, ppc32 and ppc64, have the advantage of defining
char
as an unsigned integer type, so they provide one more portability check for the same price (BLAKE3 is not written to rely on the signedness ofchar
, but since the typechar
appears in the prototypes of standard functions, it is difficult to be absolutely sure).Long story short, there was no Undefined Behavior for these big-endian platforms but they were computing different digests than the little-endian platforms. One possibility is that a bug in TrustInSoft CI's emulation of these big-endian architectures causes the execution to be imperfectly emulated, but that does not seem very likely, because any ordinary bug would already be visible for shorter plaintexts. Another possibility is that although the C implementation of BLAKE3 is written to behave the same on little- and big-endian platforms with functions named
load32
andstore32
, one spot where these functions were necessary was missed.The tests that show the wrong digest being computed are: https://dev.ci.trust-in-soft.com/projects/jakub-zwolakowski/BLAKE3/37?page=1
The same tests, with the change in this PR applied, compute the correct digest in: https://ci.trust-in-soft.com/projects/pascal-cuoq/BLAKE3/2?page=4
I expect the change to make more sense to you when you see it than it did to me when writing it. If the change does not seem to make sense, then we can investigate further.