* [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun
@ 2011-03-03 22:04 Michael Snyder
2011-03-03 22:11 ` DJ Delorie
0 siblings, 1 reply; 10+ messages in thread
From: Michael Snyder @ 2011-03-03 22:04 UTC (permalink / raw)
To: dj, gcc-patches, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 79 bytes --]
As written, the function will access element [30] of a 30-element array.
OK?
[-- Attachment #2: hashtab.txt --]
[-- Type: text/plain, Size: 764 bytes --]
2011-03-03 Michael Snyder <msnyder@vmware.com>
* hashtab.c (higher_prime_index): Prevent array overrun.
Index: hashtab.c
===================================================================
RCS file: /cvs/src/src/libiberty/hashtab.c,v
retrieving revision 1.38
diff -u -p -u -p -r1.38 hashtab.c
--- hashtab.c 3 Feb 2011 07:23:59 -0000 1.38
+++ hashtab.c 3 Mar 2011 22:01:08 -0000
@@ -173,9 +173,9 @@ static unsigned int
higher_prime_index (unsigned long n)
{
unsigned int low = 0;
- unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);
+ unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]) - 1;
- while (low != high)
+ while (low < high)
{
unsigned int mid = low + (high - low) / 2;
if (n > prime_tab[mid].prime)
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun 2011-03-03 22:04 [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun Michael Snyder @ 2011-03-03 22:11 ` DJ Delorie 2011-03-03 22:26 ` Michael Snyder 2011-03-03 22:33 ` Michael Snyder 0 siblings, 2 replies; 10+ messages in thread From: DJ Delorie @ 2011-03-03 22:11 UTC (permalink / raw) To: Michael Snyder; +Cc: gcc-patches, gdb-patches > As written, the function will access element [30] of a 30-element array. Um, no? unsigned int mid = low + (high - low) / 2; This can never give mid == high unless low == high, which won't happen in that loop. The math wants to search everything from (including) low to (excluding) high. (but I'm willing to be proven wrong...) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun 2011-03-03 22:11 ` DJ Delorie @ 2011-03-03 22:26 ` Michael Snyder 2011-03-03 22:59 ` DJ Delorie 2011-03-03 23:01 ` Mike Stump 2011-03-03 22:33 ` Michael Snyder 1 sibling, 2 replies; 10+ messages in thread From: Michael Snyder @ 2011-03-03 22:26 UTC (permalink / raw) To: DJ Delorie; +Cc: gcc-patches, gdb-patches [-- Attachment #1: Type: text/plain, Size: 772 bytes --] DJ Delorie wrote: >> As written, the function will access element [30] of a 30-element array. > > Um, no? Y-uh-huh! > unsigned int mid = low + (high - low) / 2; > > This can never give mid == high unless low == high, which won't happen > in that loop. > > The math wants to search everything from (including) low to > (excluding) high. > > (but I'm willing to be proven wrong...) I am willing to do that! ;-) Compile this program, run it under gdb with the input "0xffffffff", and step through the code. You will see it assign the value "30" to "low" and use it to access the array. I suppose you could do it directly just by loading gdb into gdb, putting a breakpoint at the above function, and then calling it from gdb with the input 0xffffffff. [-- Attachment #2: hash.c --] [-- Type: text/x-csrc, Size: 2426 bytes --] #include <stdio.h> #include <stdlib.h> typedef unsigned int hashval_t; struct prime_ent { hashval_t prime; hashval_t inv; hashval_t inv_m2; /* inverse of prime-2 */ hashval_t shift; }; static struct prime_ent const prime_tab[] = { { 7, 0x24924925, 0x9999999b, 2 }, { 13, 0x3b13b13c, 0x745d1747, 3 }, { 31, 0x08421085, 0x1a7b9612, 4 }, { 61, 0x0c9714fc, 0x15b1e5f8, 5 }, { 127, 0x02040811, 0x0624dd30, 6 }, { 251, 0x05197f7e, 0x073260a5, 7 }, { 509, 0x01824366, 0x02864fc8, 8 }, { 1021, 0x00c0906d, 0x014191f7, 9 }, { 2039, 0x0121456f, 0x0161e69e, 10 }, { 4093, 0x00300902, 0x00501908, 11 }, { 8191, 0x00080041, 0x00180241, 12 }, { 16381, 0x000c0091, 0x00140191, 13 }, { 32749, 0x002605a5, 0x002a06e6, 14 }, { 65521, 0x000f00e2, 0x00110122, 15 }, { 131071, 0x00008001, 0x00018003, 16 }, { 262139, 0x00014002, 0x0001c004, 17 }, { 524287, 0x00002001, 0x00006001, 18 }, { 1048573, 0x00003001, 0x00005001, 19 }, { 2097143, 0x00004801, 0x00005801, 20 }, { 4194301, 0x00000c01, 0x00001401, 21 }, { 8388593, 0x00001e01, 0x00002201, 22 }, { 16777213, 0x00000301, 0x00000501, 23 }, { 33554393, 0x00001381, 0x00001481, 24 }, { 67108859, 0x00000141, 0x000001c1, 25 }, { 134217689, 0x000004e1, 0x00000521, 26 }, { 268435399, 0x00000391, 0x000003b1, 27 }, { 536870909, 0x00000019, 0x00000029, 28 }, { 1073741789, 0x0000008d, 0x00000095, 29 }, { 2147483647, 0x00000003, 0x00000007, 30 }, /* Avoid "decimal constant so large it is unsigned" for 4294967291. */ { 0xfffffffb, 0x00000006, 0x00000008, 31 } }; static unsigned int higher_prime_index (unsigned long n) { unsigned int low = 0; unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]); while (low != high) { unsigned int mid = low + (high - low) / 2; if (n > prime_tab[mid].prime) low = mid + 1; else high = mid; } /* If we've run out of primes, abort. */ if (n > prime_tab[low].prime) { fprintf (stderr, "Cannot find prime bigger than %lu\n", n); abort (); } return low; } int main (int argc, char **argv) { if (argc < 2) { fprintf (stderr, "Usage: hash <number>\n"); return 1; } printf ("Answer: %d\n", higher_prime_index (strtoul (argv[1], NULL, 0))); return 0; } ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun 2011-03-03 22:26 ` Michael Snyder @ 2011-03-03 22:59 ` DJ Delorie 2011-03-07 2:59 ` Michael Snyder 2011-03-03 23:01 ` Mike Stump 1 sibling, 1 reply; 10+ messages in thread From: DJ Delorie @ 2011-03-03 22:59 UTC (permalink / raw) To: Michael Snyder; +Cc: gcc-patches, gdb-patches Bizzare, the problem isn't the hash loop, it's the error handler at the end! It never uses [30] for the main loop, only if you give it a number between 0xfffffffb and 0xffffffff - and in the case where it would use [30], it's supposed to abort anyway. I couldn't figure out why your patch worked until I realized that the main loop still fails! It works because the error handler just doesn't abort, returning the last array entry, which happens to be the right one. I think a suitable comment explaining what's actually going on, and why it still works, is warranted... but your patch is OK with me otherwise :-) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun 2011-03-03 22:59 ` DJ Delorie @ 2011-03-07 2:59 ` Michael Snyder 0 siblings, 0 replies; 10+ messages in thread From: Michael Snyder @ 2011-03-07 2:59 UTC (permalink / raw) To: DJ Delorie; +Cc: gcc-patches, gdb-patches DJ Delorie wrote: > Bizzare, the problem isn't the hash loop, it's the error handler at > the end! It never uses [30] for the main loop, only if you give it a > number between 0xfffffffb and 0xffffffff - and in the case where it > would use [30], it's supposed to abort anyway. > > I couldn't figure out why your patch worked until I realized that the > main loop still fails! It works because the error handler just > doesn't abort, returning the last array entry, which happens to be the > right one. > > I think a suitable comment explaining what's actually going on, and > why it still works, is warranted... but your patch is OK with me > otherwise :-) Please give me the comment, and I'll check it in. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun 2011-03-03 22:26 ` Michael Snyder 2011-03-03 22:59 ` DJ Delorie @ 2011-03-03 23:01 ` Mike Stump 2011-03-03 23:24 ` Michael Snyder 2011-03-04 0:14 ` Dave Korn 1 sibling, 2 replies; 10+ messages in thread From: Mike Stump @ 2011-03-03 23:01 UTC (permalink / raw) To: Michael Snyder; +Cc: DJ Delorie, gcc-patches, gdb-patches On Mar 3, 2011, at 2:26 PM, Michael Snyder wrote: > DJ Delorie wrote: >>> As written, the function will access element [30] of a 30-element array. >> Um, no? > > Y-uh-huh! fight fight fight... :-) There can be only one. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun 2011-03-03 23:01 ` Mike Stump @ 2011-03-03 23:24 ` Michael Snyder 2011-03-04 0:14 ` Dave Korn 1 sibling, 0 replies; 10+ messages in thread From: Michael Snyder @ 2011-03-03 23:24 UTC (permalink / raw) To: Mike Stump; +Cc: DJ Delorie, gcc-patches, gdb-patches Mike Stump wrote: > On Mar 3, 2011, at 2:26 PM, Michael Snyder wrote: >> DJ Delorie wrote: >>>> As written, the function will access element [30] of a 30-element array. >>> Um, no? >> Y-uh-huh! > > fight fight fight... :-) There can be only one. Oh, did I forget the smiley? ;-) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun 2011-03-03 23:01 ` Mike Stump 2011-03-03 23:24 ` Michael Snyder @ 2011-03-04 0:14 ` Dave Korn 2011-03-04 0:19 ` DJ Delorie 1 sibling, 1 reply; 10+ messages in thread From: Dave Korn @ 2011-03-04 0:14 UTC (permalink / raw) To: Mike Stump; +Cc: Michael Snyder, DJ Delorie, gcc-patches, gdb-patches On 03/03/2011 23:00, Mike Stump wrote: > On Mar 3, 2011, at 2:26 PM, Michael Snyder wrote: >> DJ Delorie wrote: >>>> As written, the function will access element [30] of a 30-element array. >>> Um, no? >> Y-uh-huh! > > fight fight fight... :-) There can be only one. I was just wondering whether now would be a good time to mention that having prime-sized hash tables is only a workaround against the danger of someone providing an inadequate hash function implementation in the first place? cheers, DaveK ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun 2011-03-04 0:14 ` Dave Korn @ 2011-03-04 0:19 ` DJ Delorie 0 siblings, 0 replies; 10+ messages in thread From: DJ Delorie @ 2011-03-04 0:19 UTC (permalink / raw) To: Dave Korn; +Cc: gcc-patches, gdb-patches > I was just wondering whether now would be a good time to mention Probably not, gcc being in stage 4 and all... ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun 2011-03-03 22:11 ` DJ Delorie 2011-03-03 22:26 ` Michael Snyder @ 2011-03-03 22:33 ` Michael Snyder 1 sibling, 0 replies; 10+ messages in thread From: Michael Snyder @ 2011-03-03 22:33 UTC (permalink / raw) To: DJ Delorie; +Cc: gcc-patches, gdb-patches DJ Delorie wrote: >> As written, the function will access element [30] of a 30-element array. > > Um, no? > > unsigned int mid = low + (high - low) / 2; > > This can never give mid == high unless low == high, which won't happen > in that loop. > > The math wants to search everything from (including) low to > (excluding) high. > > (but I'm willing to be proven wrong...) Whee, here we go... (gdb) b higher_prime_index Breakpoint 2 at 0x79bed4: file /data/home/msnyder/cvs/localhost/src/libiberty/hashtab.c, line 175. (gdb) print higher_prime_index(0xffffffff) Breakpoint 2, higher_prime_index (n=4294967295) at /data/home/msnyder/cvs/localhost/src/libiberty/hashtab.c:175 175 unsigned int low = 0; The program being debugged stopped while in a function called from GDB. Evaluation of the expression containing the function (higher_prime_index) will be abandoned. When the function is done executing, GDB will silently stop. (gdb) n 176 unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]) - 1; (gdb) 178 while (low < high) (gdb) 180 unsigned int mid = low + (high - low) / 2; (gdb) display low 1: low = 0 (gdb) n 181 if (n > prime_tab[mid].prime) 1: low = 0 (gdb) 182 low = mid + 1; 1: low = 0(gdb) b higher_prime_index Breakpoint 2 at 0x79bed4: file /data/home/msnyder/cvs/localhost/src/libiberty/hashtab.c, line 175. (gdb) print higher_prime_index(0xffffffff) Breakpoint 2, higher_prime_index (n=4294967295) at /data/home/msnyder/cvs/localhost/src/libiberty/hashtab.c:175 175 unsigned int low = 0; The program being debugged stopped while in a function called from GDB. Evaluation of the expression containing the function (higher_prime_index) will be abandoned. When the function is done executing, GDB will silently stop. (gdb) n 176 unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]) - 1; (gdb) 178 while (low < high) (gdb) 180 unsigned int mid = low + (high - low) / 2; (gdb) display low 1: low = 0 (gdb) n 181 if (n > prime_tab[mid].prime) 1: low = 0 (gdb) 182 low = mid + 1; 1: low = 0 (gdb) 178 while (low < high) 1: low = 16 (gdb) 180 unsigned int mid = low + (high - low) / 2; 1: low = 16 (gdb) 181 if (n > prime_tab[mid].prime) 1: low = 16 (gdb) 182 low = mid + 1; (gdb) 178 while (low < high) 1: low = 16 (gdb) 180 unsigned int mid = low + (high - low) / 2; 1: low = 16 (gdb) 181 if (n > prime_tab[mid].prime) 1: low = 16 (gdb) 182 low = mid + 1; 1: low = 16 (gdb) 178 while (low < high) 1: low = 24 (gdb) 180 unsigned int mid = low + (high - low) / 2; 1: low = 24 (gdb) 181 if (n > prime_tab[mid].prime) 1: low = 24 (gdb) 182 low = mid + 1; 1: low = 24 (gdb) 178 while (low < high) 1: low = 28 (gdb) 180 unsigned int mid = low + (high - low) / 2; 1: low = 28 (gdb) 181 if (n > prime_tab[mid].prime) 1: low = 28 (gdb) 182 low = mid + 1; 1: low = 28 (gdb) 178 while (low < high) 1: low = 30 (gdb) 188 if (n > prime_tab[low].prime) 1: low = 30 (gdb) ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-03-07 0:51 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-03-03 22:04 [RFA] libiberty/hashtab.c, higher_prime_index: avoid array overrun Michael Snyder 2011-03-03 22:11 ` DJ Delorie 2011-03-03 22:26 ` Michael Snyder 2011-03-03 22:59 ` DJ Delorie 2011-03-07 2:59 ` Michael Snyder 2011-03-03 23:01 ` Mike Stump 2011-03-03 23:24 ` Michael Snyder 2011-03-04 0:14 ` Dave Korn 2011-03-04 0:19 ` DJ Delorie 2011-03-03 22:33 ` Michael Snyder
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox