Bug 5614 - Optimized strtok_r fails to set *save_ptr in some circumstances
Summary: Optimized strtok_r fails to set *save_ptr in some circumstances
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-01-14 21:50 UTC by Ben Pfaff
Modified: 2014-07-03 11:42 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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.