Build error with -fsanitize=address,undefined -O0 #868

issue guidovranken opened this issue on January 17, 2021
  1. guidovranken commented at 7:53 PM on January 17, 2021: none

    Set env:

    export CC=clang-11
    export CFLAGS="-fsanitize=address,undefined -O0"
    

    (This is a valid combination of compile flags that works with any other project)

    Then ./configure and build:

      CC       src/libsecp256k1_la-secp256k1.lo
    In file included from src/secp256k1.c:13:
    In file included from ./src/field_impl.h:18:
    In file included from ./src/field_5x52_impl.h:18:
    ./src/field_5x52_asm_impl.h:29:5: error: inline assembly requires more registers than available
        "movq 0(%%rsi),%%r10\n"
        ^
    ./src/field_5x52_asm_impl.h:29:5: error: inline assembly requires more registers than available
    ./src/field_5x52_asm_impl.h:29:5: error: inline assembly requires more registers than available
    ./src/field_5x52_asm_impl.h:299:5: error: inline assembly requires more registers than available
        "movq 0(%%rsi),%%r10\n"
        ^
    ./src/field_5x52_asm_impl.h:299:5: error: inline assembly requires more registers than available
    ./src/field_5x52_asm_impl.h:299:5: error: inline assembly requires more registers than available
    In file included from src/secp256k1.c:14:
    In file included from ./src/scalar_impl.h:24:
    ./src/scalar_4x64_impl.h:279:5: error: inline assembly requires more registers than available
        "movq 32(%%rsi), %%r11\n"
        ^
    ./src/scalar_4x64_impl.h:279:5: error: inline assembly requires more registers than available
    ./src/scalar_4x64_impl.h:279:5: error: inline assembly requires more registers than available
    9 errors generated.
    Makefile:1054: recipe for target 'src/libsecp256k1_la-secp256k1.lo' failed
    

    Tested with Clang 11 and latest repository checkout on Linux 64 bit.

  2. gmaxwell commented at 8:36 PM on January 17, 2021: contributor

    Looks like a clang bug to me. If it needs more registers for its own usage, its free to save something onto the stack to get enough for the assembly. Looks like there a number of unresolved reports of similar in their bug tracker: https://bugs.llvm.org/buglist.cgi?quicksearch=%22inline%20assembly%20requires%20more%20registers%20than%20available%22%20

    You can disable assembly in this library or presumably use different compiler flags to avoid the issue.

  3. guidovranken commented at 8:45 PM on January 17, 2021: none

    Got it, thanks.

  4. guidovranken closed this on Jan 17, 2021

  5. sipa commented at 8:46 PM on January 17, 2021: contributor

    I remember when writing this code originally it was hard to not run out of registers, and initially it needed -fomit-frame-pointer. That's no longer needed, but we're probably still very close to the limit. If enabling these sanitizers reserves more registers from something else, it's not unreasonable that it causes failure.

  6. real-or-random commented at 10:08 AM on January 18, 2021: contributor

    Fwiw, you see essentially the same error with ./configure CFLAGS="-fsanitize=address -O0" CC=gcc But in the case of gcc, -fomit-frame-pointer is enough (which is in -O1). For clang, you apparently need some other flags in -O1. Just passing -O1 already works.

    Can I ask why you compile with -O0? Is there some evidence that this provides "better" results for the sanitizers?

    see #846#issue-517906691 where I ran into the same issue.

  7. guidovranken commented at 10:39 AM on January 18, 2021: none

    -O0 can certainly bring to light bugs which do not manifest in high(er) optimization levels. A simple example is the statement

    (void)strlen(s);
    

    There's a good chance that will be optimized away with -O3 because it's essentially a no-op (the result of strlen isn't used, nor does strlen alter s, so removing it results in an equivalent program). But there's an OOB read there if s is an invalid pointer (or a string that is not NULL-terminated). Hence you can find this bug with -O0 but not -O3.

    Similarly other code may be elided too when using optimization (according to any logic the compiler deems appropriate) so I occasionally run things with -O0 to get the most "verbatim" binary representation of the source code to potentially find new bugs.

    Aggressive optimizations like -O3 can sometimes be useful to find undefined behavior (that's not detected by UBSAN, which only detects a small subset of all undefined behavior in C). If you start running into logic bugs or crashes that are not logical in relation to what the source code prescribes with -O3 that's often a manifestation of UB.

    OSS-Fuzz strikes a balance by compiling everything with -O1 by default.


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/secp256k1. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-23 01:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me