Make _gcry_burn_stack use variable length array
authorJussi Kivilinna <jussi.kivilinna@iki.fi>
Wed, 4 Sep 2013 07:00:45 +0000 (10:00 +0300)
committerJussi Kivilinna <jussi.kivilinna@iki.fi>
Wed, 4 Sep 2013 07:00:45 +0000 (10:00 +0300)
* configure.ac (HAVE_VLA): Add check.
* src/misc.c (_gcry_burn_stack) [HAVE_VLA]: Add VLA code.
--

Some gcc versions convert _gcry_burn_stack into loop that overwrites the same
64-byte stack buffer instead of burn stack deeper. It's argued at GCC bugzilla
that _gcry_burn_stack is doing wrong thing here [1] and that this kind of
optimization is allowed.

So lets fix _gcry_burn_stack by using variable length array when VLAs are
supported by compiler. This should ensure proper stack burning to the requested
depth and avoid GCC loop optimizations.

[1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52285

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
configure.ac
src/misc.c

index 959327a..993577b 100644 (file)
@@ -764,6 +764,24 @@ case "${host}" in
 esac
 AC_SUBST(FALLBACK_SOCKLEN_T)
 
+
+#
+# Check for VLA support (variable length arrays).
+#
+AC_CACHE_CHECK(whether the variable length arrays are supported,
+       [gcry_cv_have_vla],
+       [gcry_cv_have_vla=no
+        AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          [[void f1(char *, int);
+            char foo(int i) {
+              char b[(i < 0 ? 0 : i) + 1];
+              f1(b, sizeof b); return b[0];}]])],
+          [gcry_cv_have_vla=yes])])
+if test "$gcry_cv_have_vla" = "yes" ; then
+   AC_DEFINE(HAVE_VLA,1, [Defined if variable length arrays are supported])
+fi
+
+
 #
 # Check for ELF visibility support.
 #
index 2d9c73a..135aeb4 100644 (file)
@@ -290,13 +290,20 @@ _gcry_log_printhex (const char *text, const void *buffer, size_t length)
 void
 _gcry_burn_stack (int bytes)
 {
-    char buf[64];
+#ifdef HAVE_VLA
+    int buflen = (((bytes <= 0) ? 1 : bytes) + 63) & ~63;
+    volatile char buf[buflen];
+
+    wipememory (buf, sizeof buf);
+#else
+    volatile char buf[64];
 
     wipememory (buf, sizeof buf);
 
     bytes -= sizeof buf;
     if (bytes > 0)
         _gcry_burn_stack (bytes);
+#endif
 }
 
 void