Bug 5614

Summary: Optimized strtok_r fails to set *save_ptr in some circumstances
Product: glibc Reporter: Ben Pfaff <blp>
Component: libcAssignee: Ulrich Drepper <drepper.fsp>
Status: RESOLVED FIXED    
Severity: normal CC: glibc-bugs, null
Priority: P2 Flags: fweimer: security-
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description Ben Pfaff 2008-01-14 21:50:24 UTC
The following program should print a line like
   token1=(nil) save_ptr=0xbfd44dbb
and execute successfully, but when it is compiled with "gcc -O2" it will print
   token1=(nil) save_ptr=0xc0ffee
and segfault in the second call to strtok_r.  The reason is that the optimized
version of strtok_r in string/bits/string2.h, __strtok_r_1c, does not always set
its *__nextp argument: if the remainder of the string is empty or consists only
of delimiters, then it returns without setting it.

This behavior does not show up when compiling without optimization, as the
optimized version of strtok_r is not used in that case.

This is with glibc 2.7-3 and GCC 4.1.3 on a Debian GNU/Linux i386 (unstable)
platform.

I believe that this behavior is contrary to SUSv3, which states: "In the first
call to strtok_r(), s points to a null-terminated string, sep to a
null-terminated string of separator characters, and the value pointed to by
lasts is ignored. The strtok_r() function shall return a pointer to the first
character of the first token, write a null character into s immediately
following the returned token, and update the pointer to which lasts points."

#include <stdio.h>
#include <string.h>

int
main (void) 
{
    char string[] = ":::";
    char *save_ptr = (char *) 0xc0ffee;
    char *token1, *token2;
    token1 = strtok_r (string, ":", &save_ptr);
    printf("token1=%p save_ptr=%p\n", token1, save_ptr);
    token2 = strtok_r (NULL, ":", &save_ptr);
    return 0;
}
Comment 1 Ulrich Drepper 2008-01-15 19:12:31 UTC
Fixed in cvs.