[PATCH] Prevent tail call optimization with _gcry_burn_stack
Jussi Kivilinna
jussi.kivilinna at iki.fi
Thu Sep 26 11:54:06 CEST 2013
* src/g10lib.h (_gcry_burn_stack): Rename to __gcry_burn_stack.
(__gcry_burn_stack_dummy): New.
(_gcry_burn_stack): New macro.
* src/misc.c (_gcry_burn_stack): Rename to __gcry_burn_stack.
(__gcry_burn_stack_dummy): New.
--
Tail call optimization can turn _gcry_burn_stack call in to tail jump. When
this happens, stack pointer is restored to initial state of current function.
This causes problem for _gcry_burn_stack because its callers do not count in
current function stack depth.
One solution is to prevent gcry_burn_stack being tail optimized by inserting
dummy function call behind it.
(Another would be to add memory barrier 'asm volatile("":::"memory")' behind
every_gcry_burn_stack. This however requires GCC asm support from compiler.)
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
src/g10lib.h | 6 +++++-
src/misc.c | 7 ++++++-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/g10lib.h b/src/g10lib.h
index 73ba683..9b342c3 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -250,7 +250,11 @@ int strcasecmp (const char *a, const char *b) _GCRY_GCC_ATTR_PURE;
/* Stack burning. */
-void _gcry_burn_stack (unsigned int bytes);
+void __gcry_burn_stack_dummy (void);
+void __gcry_burn_stack (unsigned int bytes);
+#define _gcry_burn_stack(bytes) \
+ do { __gcry_burn_stack (bytes); \
+ __gcry_burn_stack_dummy (); } while(0)
/* To avoid that a compiler optimizes certain memset calls away, these
diff --git a/src/misc.c b/src/misc.c
index a19e1e4..83a3a9e 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -363,7 +363,7 @@ _gcry_log_printmpi (const char *text, gcry_mpi_t mpi)
void
-_gcry_burn_stack (unsigned int bytes)
+__gcry_burn_stack (unsigned int bytes)
{
#ifdef HAVE_VLA
/* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */
@@ -382,6 +382,11 @@ _gcry_burn_stack (unsigned int bytes)
}
void
+__gcry_burn_stack_dummy (void)
+{
+}
+
+void
_gcry_divide_by_zero (void)
{
gpg_err_set_errno (EDOM);
More information about the Gcrypt-devel
mailing list