I know that almost no one uses emutls, but I was fiddling with
it recently, and found a buffer overflow; the emutls_destroy()
function moves past the end of an array.  Patch attached.

The correctness of the fix may not be immediately obvious, but
a careful study of emutls_alloc() will show that there is some
off-by-one tomfoolery, coded in on purpose (personally, I think
its poor/bad coding style). The corresponding tomfoolery
wasn't done in the matching free code, leading to this bug.

---
 gcc/emutls.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

Index: gcc-4.4/gcc/emutls.c
===================================================================
--- gcc-4.4.orig/gcc/emutls.c   2010-12-13 16:53:48.000000000 -0600
+++ gcc-4.4/gcc/emutls.c        2010-12-13 17:12:27.000000000 -0600
@@ -76,7 +76,11 @@ emutls_destroy (void *ptr)
   pointer size = arr->size;
   pointer i;

-  for (i = 0; i < size; ++i)
+  /* arr->size is the total size of area that 'arr' is pointing to.
+   * The size of 'arr->data' is one less than that.
+   * Properly, its (&arr->data[0]-arr)/sizeof(void *) = 1 less.
+   */
+  for (i = 0; i < size-1; ++i)
     {
       if (arr->data[i])
        free (arr->data[i][-1]);

Reply via email to