[php-src] Issue #12592: strcspn() odd behaviour with NUL bytes and empty mask

From: Date: Wed, 01 Nov 2023 20:48:29 +0000
Subject: [php-src] Issue #12592: strcspn() odd behaviour with NUL bytes and empty mask
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-245716@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/12592 Author: nielsdos ### Description The following code: ```php <?php var_dump(strcspn("abc\0def", " ")); var_dump(strcspn("abc\0def", "")); ``` Resulted in this output: ``` int(7) int(3) ``` But I expected this output instead: ``` int(7) int(7) ``` Looking at the description of strcspn: > Returns the length of the initial segment of string which does not contain any of the > characters in characters. IOW, if the mask is empty, the stop condition is never met so the total length of the string must be returned, no? I discovered this while I was working on an optimization for this function similar to what I did for strspn. This has been wrong since 1999: a15916a47aba3e89d2b6cad8533868c7ee958c25 There are actually tests that check this behaviour, but I think that's just incidental as the test date from way later than 1999. The reason this happens is because php_strcspn accesses *s2 even if it is empty, thus reading a NUL byte out of bounds and thinking that the NUL is part of the mask. Fixing this is trivial however, although I wouldn't recommend doing this in stable branches as it is a behaviour change, although a weird one: ```diff diff --git a/ext/standard/string.c b/ext/standard/string.c index 8beedfe818..b5deb20403 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1640,16 +1640,16 @@ PHPAPI size_t php_strcspn(const char *s1, const char *s2, const char *s1_end, co const char *p, *spanp; char c = *s1; - for (p = s1;;) { - spanp = s2; - do { - if (*spanp == c || p == s1_end) { + for (p = s1; p < s1_end;) { + for (spanp = s2; spanp < s2_end; spanp++) { + if (*spanp == c) { return p - s1; } - } while (spanp++ < (s2_end - 1)); + } c = *++p; } - /* NOTREACHED */ + + return p - s1; } /* }}} */ ``` I'd say: let's fix it only in master? ### PHP Version Every version since 1999 ### Operating System _No response_

« previous php.bugs (#245716) next »