Hi Basil, "Basil L. Contovounesios" <[email protected]> writes:
> When compiling my project with Clang, ASan, and Gnulib's stdint-h, > I find that PTRDIFF_MAX and SIZE_MAX expand to 1. > > This does not happen if I either > - remove stdint-h from bootstrap.conf; or > - disable ASan; or > - use GCC. > > I am reproducing the issue in a dummy project as follows: > 0. git clone 'https://git.sr.ht/~blc/foo' && cd foo > 1. ./test gcc > 2. ./test gcc --enable-asan > 3. ./test clang > 4. ./test clang --enable-asan > > Steps 1-3 end in > bar> 13 `Hello, World!' > as expected, whereas step 4 ends in > foo> Overflow 13 > 1 > where 13 (the length of "Hello, World!") exceeds 1 (PTRDIFF_MAX). > > This happens in the following function in src/foo.c: > > bool > foo_string (char const str[const static 1]) > { > size_t const len = strlen (str); > bool ok = len <= (uintmax_t) PTRDIFF_MAX; > if (ok) > bar_string (str, len); > else > fprintf (stderr, "foo> Overflow %zu > %td\n", len, PTRDIFF_MAX); > return ok; > } > > The files under src/ should be straightforward; the only complexities > should be in configure.ac (where I define a macro inspired by > gl_COMPILER_OPTION_IF and AX_CHECK_LINK_FLAG) and the 'test' script > which tries to set up ASan and all of its run time options for either > GCC or Clang. > > Note that configure.ac enables UBSan as well if available, but disabling > that by passing --disable-ubsan to the 'test' script makes no observable > difference in the behaviour of the 'foo' program. > > I have tried removing other header modules from bootstrap.conf, > but only the removal of stdint-h resolves the issue. > > That's as far as I've been able to troubleshoot for now; > let me know if you have any further suggestions. Thanks for the reproduction steps. Do you see the same as me when running these commands: $ grep '^BITSIZEOF_PTRDIFF_T' Makefile BITSIZEOF_PTRDIFF_T = 0 $ grep -FA5 'checking for bit size of ptrdiff_t' config.log configure:9072: checking for bit size of ptrdiff_t configure:9078: clang -std=gnu23 -o conftest -Og -g3 -ggdb3 -gdwarf-5 -fdebug-macro -fsanitize=address -fsanitize=undefined -shared-libasan -fsanitize=address -fsanitize=undefined conftest.c >&5 configure:9078: $? = 0 configure:9078: ./conftest ./conftest: error while loading shared libraries: libclang_rt.asan.so: cannot open shared object file: No such file or directory configure:9078: $? = 127 If so, then this expression from stdint.in.h: # define PTRDIFF_MAX \ _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) Turns into: # define PTRDIFF_MAX \ _STDINT_MAX (1, 0, 0l) Here is what that expands to using a test program: $ cat main.c #include <stdio.h> #include <inttypes.h> # define _STDINT_MAX(signed, bits, zero) \ (((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1) int main (void) { printf ("%ju\n", (uintmax_t) _STDINT_MAX (1, 0, 0l)); return 0; } $ gcc main.c $ ./a.out 1 > By the way, does it make sense to update the Info node > "(gnulib) Writing reliable code" to mention any of > _FORTIFY_SOURCE=3, GCC's -fhardened, or -fsanitize-trap=all in > place of the now-deprecated -fsanitize-undefined-trap-on-error? That sounds reasonable to me, but I would have to look into what those mean. Source fortification nice, but I forget the difference between the levels. Collin
