Bug#635885: libc6: strchr() behavior changed
Package: libc6
Version: 2.11.2-10
strchr(3) doesn't return correct value on certain input. Here is a test
case that describes the problem:
$ cat test_strchr.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void my_strchr(const char *s, int c)
{
char *r = strchr(s, c);
printf("strchr(%d [%d]) = [%d]\n",
(int) (unsigned char) c, c,
(int) (unsigned char) (r ? *r : 0));
}
int main()
{
static const char s[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0};
char ch = 228;
int d = 228;
my_strchr(s, ch);
my_strchr(s, (int) ch);
my_strchr(s, (unsigned int) ch);
my_strchr(s, (unsigned char) ch);
my_strchr(s, d);
return 0;
}
When running this application on Debian with libc6 2.7-18lenny2 and on my
Gentoo machine I get:
$ ./test_strchr
strchr(228 [-28]) = [0]
strchr(228 [-28]) = [0]
strchr(228 [-28]) = [0]
strchr(228 [228]) = [0]
strchr(228 [228]) = [0]
When running it on Debian with libc6 2.11.2-10:
strchr(228 [-28]) = [255]
strchr(228 [-28]) = [255]
strchr(228 [-28]) = [255]
strchr(228 [228]) = [0]
strchr(228 [228]) = [0]
When the second argument passed to strchr() is negative (i.e. it's a char
with value greater than 127), strchr() incorrectly matches it to
character with value of -1.
Passing positive int or char cast to (unsigned char) fixes this problem,
but I don't think this is a solution. I would expect strchr() to behave
consistently accross different versions and I don't think that invoking
char c = 228 /* or "-28" or some latin9 character with diacritics */
char *r = strchr(s, c);
should lead to r containing something other than NULL.
From strchr() manpage
Here "character" means "byte"; these functions do not work with
wide or multibyte characters.
So I would expect strchr() to work correctly with _bytes_, not only bytes
lower than 128.
Reply to: