Eric Blake wrote: > > I don't think it is a bug. memchr could also be implemented by doing > > a backwards search and still be conforming to ISO C99 and POSIX: > > The Austin Group disagrees with you. Here is the results from the meeting > yesterday > (https://www.opengroup.org/sophocles/show_mail.tpl?CALLER=index.tpl&source=L&listname=austin-group-l&id=12144):
Thanks for bringing up the issue. I'm glad that we can now expect as much from memchr() as from strlen(). It's easier to fix the one or two buggy implementations of memchr() out there [1][2][3] than to review all uses, in strstr, vasnprintf, and many more. > But as there are systems in the wild with the broken implementation, we > should probably start worrying about replacing the buggy memchr > implementations. As a first step, let me add a test to test-memchr. Let's see whether we get some reports about it. - Probably we also should undeprecate 'memchr', so that its unit test gets included into m4, gettext, coreutils, etc.? Bruno [1] http://www.alphalinux.org/archives/axp-list/March2001/0337.shtml [2] http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=521737 [3] http://sourceware.org/bugzilla/show_bug.cgi?id=10162 2009-05-31 Bruno Haible <[email protected]> * tests/zerosize-ptr.h (zerosize_ptr): Specify more details. * tests/test-memchr.c (main): Check that memchr does not read past the first occurrence of the byte. * tests/test-strstr.c (main): Update comment. Suggested by Eric Blake. *** tests/zerosize-ptr.h.orig 2009-05-31 14:35:16.000000000 +0200 --- tests/zerosize-ptr.h 2009-05-31 14:34:04.000000000 +0200 *************** *** 35,41 **** # endif #endif ! /* Return a pointer to a zero-size object in memory, if possible. Return NULL otherwise. */ static void * --- 35,43 ---- # endif #endif ! /* Return a pointer to a zero-size object in memory (that is, actually, a ! pointer to a page boundary where the previous page is readable and writable ! and the next page is neither readable not writable), if possible. Return NULL otherwise. */ static void * *** tests/test-memchr.c.orig 2009-05-31 14:35:16.000000000 +0200 --- tests/test-memchr.c 2009-05-31 14:35:03.000000000 +0200 *************** *** 94,99 **** --- 94,129 ---- } } + /* Check that memchr() does not read past the first occurrence of the + byte being searched. See the Austin Group's clarification + <http://www.opengroup.org/austin/docs/austin_454.txt>. */ + { + char *page_boundary = (char *) zerosize_ptr (); + + if (page_boundary != NULL) + { + int n; + + for (n = 1; n <= 500; n++) + { + char *mem = page_boundary - n; + memset (mem, 'X', n); + ASSERT (MEMCHR (mem, 'U', n) == NULL); + + { + int i; + + for (i = 0; i < n; i++) + { + mem[i] = 'U'; + ASSERT (MEMCHR (mem, 'U', 4000) == mem + i); + mem[i] = 'X'; + } + } + } + } + } + free (input); return 0; *** tests/test-strstr.c.orig 2009-05-31 14:35:16.000000000 +0200 --- tests/test-strstr.c 2009-05-31 14:20:37.000000000 +0200 *************** *** 61,67 **** } { ! /* See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=521737 */ const char *fix = "aBaaaaaaaaaaax"; char *input = malloc (strlen (fix) + 1); const char *result; --- 61,72 ---- } { ! /* On some platforms, the memchr() functions reads past the first ! occurrence of the byte to be searched, leading to an out-of-bounds ! read access for strstr(). ! See <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=521737>. ! This is a bug in memchr(), see the Austin Group's clarification ! <http://www.opengroup.org/austin/docs/austin_454.txt>. */ const char *fix = "aBaaaaaaaaaaax"; char *input = malloc (strlen (fix) + 1); const char *result;
