On Monday 16 June 2008 06:33:35 you wrote:
> On Sunday 15 June 2008 23:06, Tito wrote:
> > Hi,
> > while inspecting the last changes in busybox code I hit some issues in
> > libbb/strrstr.c. The strrtstr function fails on some corner cases of a
> > little
> > test program I wrote (and bombs out on NULL pointers):
> >
> > char* strrstr(const char *haystack, const char *needle)
> > {
> > char *tmp = strrchr(haystack, *needle);
> > if (tmp == NULL || strcmp(tmp, needle) != 0)
> > return NULL;
> > return tmp;
> > }
> >
> >
> > ./test
> > 'baaabaaab' vs. 'aaa' : FAILED
> > 'baaabaaaab' vs. 'aaa' : FAILED
> > 'baaabaab' vs. 'aaa' : FAILED
> > 'aaa' vs. 'aaa' : FAILED
> > 'aaa' vs. 'a' : PASSED
> > 'aaa' vs. 'bbb' : PASSED
> > 'a' vs. 'aaa' : PASSED
> > 'aaa' vs. '' : FAILED
> > '' vs. 'aaa' : PASSED
> > '' vs. '' : FAILED
> > Segmentation fault
> >
> > I've tried to write a more robust variant:
> >
> > /*
> > * The strrstr() function finds the last occurrence of the nul terminated
> > * substring needle in the nul terminated string haystack. The terminating
> > * nul characters or NULL pointers are not compared.
> > */
>
> Why is it important to work with NULLs?
> E.g. strlen would SEGV on NULL.
Hi,
It is just my way of doing things, I don't like functions that segfault
on NULL as usually most of the times you have to add guards in the calling
code, but as said this part of the code could easily be removed
so that the size is almost the same as before.
There was one more reason to avoid strlen, but it was just my personal stupid
paranoia:
as we don't know the lenght of the strings it was difficult to decide
the correct type for the result to avoid possible overflows
OTOH using the biggest looked like overkill,
so I decided to walk to the end of the string instead.
> Mine version is:
>
> char* strrstr(const char *haystack, const char *needle)
> {
> char *r = NULL;
>
> if (!needle[0])
> return r;
> while (1) {
> char *p = strstr(haystack, needle);
> if (!p)
> return r;
> r = p;
> haystack = p + 1;
> }
> }
>
> # ./a.out
> 'baaabaaab' vs. 'aaa' : PASSED
> 'baaabaaaab' vs. 'aaa' : PASSED
> 'baaabaab' vs. 'aaa' : PASSED
> 'aaa' vs. 'aaa' : PASSED
> 'aaa' vs. 'a' : PASSED
> 'aaa' vs. 'bbb' : PASSED
> 'a' vs. 'aaa' : PASSED
> 'aaa' vs. '' : PASSED
> '' vs. 'aaa' : PASSED
> '' vs. '' : PASSED
> (cases with NULLs are not tested)
>
> Comparing with current busybox:
>
> function old new delta
> strrstr 53 42 -11
>
> BTW, is it normal:
>
> ret |= !(n = (strrstr("aaa", "") == NULL));
> printf("'aaa' vs. '' : %s\n", n ? "PASSED" :
> "FAILED");
> ret |= !(n = (strrstr("", "") == NULL));
> printf("'' vs. '' : %s\n", n ? "PASSED" :
> "FAILED");
>
> "" needle definitely CAN be found in (any) haystack. Why we return NULL?!
I misunderstood the man page:
DESCRIPTION
The strstr() function finds the first occurrence of the substring needle
in the string haystack. The terminating ’\0’ characters are not
compared.
I thought "" is '\0' and should not be compared. But by running a little
test program the behaviour of strstr seems to be different, so this certainly
needs to be fixed :
int main(int argc, char **argv)
{
printf("strstr(aaa,'') returns %sNULL\n", (strstr("aaa", "") == NULL) ?
"" :"not-");
printf("%s\n", strstr("aaa", ""));
printf("strstr('','') returns %sNULL\n", (strstr("", "") == NULL) ? ""
:"not-");
printf("%s\n", strstr("", ""));
return 0;
}
./test2
strstr(aaa,"") returns not-NULL
aaa
strstr("","") returns not-NULL
debian:~/Desktop#
Ciao,
Tito
> --
> vda
>
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox