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]);