bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

explicit_bzero test: Fix test failure due to GCC optimizations


From: Bruno Haible
Subject: explicit_bzero test: Fix test failure due to GCC optimizations
Date: Sun, 29 Aug 2021 19:03:55 +0200

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  <bruno@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






reply via email to

[Prev in Thread] Current Thread [Next in Thread]