The explicit_bzero test (which needs to do things that are outside of the C standard) fails in different circumstances, due to GCC optimizations:
1) On x86_64, with GCC 11 and option -O3, as well as on m68k with GCC 10 and option -O3, the compiler creates two simplified copies of the function do_secret_stuff, one for pass==1, and one for pass!=1. The stack allocation of both simplified copies is different. The fix is to have a static variable communicate the address of stackbuf from the first invocation (pass==1) to the second invocation (pass==2). 2) On m68k with GCC 10 and option -O2, the compiler generates code for do_secret_stuff (1); count += do_secret_stuff (2); that cleans up the stack only after the second statement. This is possible because m68k has a small stack alignment. But the consequence is that the stack pointer in the two calls is different; this makes the test fail. The fix is to convince the compiler to use the stack pointer in both cases. 2021-08-29 Bruno Haible <br...@clisp.org> explicit_bzero test: Fix test failure due to GCC optimizations. * tests/test-explicit_bzero.c (do_secret_stuff): Use static variable 'last_stackbuf'. (main): Use an 'if' to combine the two do_secret_stuff invocations. diff --git a/tests/test-explicit_bzero.c b/tests/test-explicit_bzero.c index 14f0ead2b..15a252698 100644 --- a/tests/test-explicit_bzero.c +++ b/tests/test-explicit_bzero.c @@ -139,16 +139,22 @@ test_heap (void) static int _GL_ATTRIBUTE_NOINLINE do_secret_stuff (volatile int pass) { + static char *last_stackbuf; char stackbuf[SECRET_SIZE]; if (pass == 1) { memcpy (stackbuf, SECRET, SECRET_SIZE); explicit_bzero (stackbuf, SECRET_SIZE); + last_stackbuf = stackbuf; return 0; } else /* pass == 2 */ { - return memcmp (zero, stackbuf, SECRET_SIZE) != 0; + /* Use last_stackbuf here, because stackbuf may be allocated at a + different address than last_stackbuf. This can happen + when the compiler splits this function into different functions, + one for pass == 1 and one for pass != 1. */ + return memcmp (zero, last_stackbuf, SECRET_SIZE) != 0; } } @@ -158,10 +164,17 @@ test_stack (void) int count = 0; int repeat; - for (repeat = 1000; repeat > 0; repeat--) + for (repeat = 2 * 1000; repeat > 0; repeat--) { - do_secret_stuff (1); - count += do_secret_stuff (2); + /* This odd way of writing two consecutive statements + do_secret_stuff (1); + count += do_secret_stuff (2); + ensures that the two do_secret_stuff calls are performed with the same + stack pointer value, on m68k. */ + if ((repeat % 2) == 0) + do_secret_stuff (1); + else + count += do_secret_stuff (2); } /* If explicit_bzero works, count is near 0. (It may be > 0 if there were some asynchronous signal invocations between the two calls of