I've stumbled upon an issue with strstr in an old legacy codebase. There's lot of code, but basically the test case would come down to this:
$value = 2660;
$link = 'affiliateid=1449&zoneid=6011&placement_id=11736&publisher_id=1449&period_preset=yesterday&period_start=2017-03-27&period_end=2017-03-27';
var_dump(strstr($link, $value));
I would expect this to return false
since "2660" is not in the string however it returns d=1449&zoneid=6011&placement_id=11736&publisher_id=1449&period_preset=yesterday&period_start=2017-03-27&period_end=2017-03-27
.
I realise that $value
should be a string but still I don't understand why it's not casted to a string by PHP and why it's finding this number in the link.
Actually, if I try with $value = '2660';
it returns false
as expected.
Any idea what's happening?
It's because fgets stores the newline character so when strstr does a comparison it fails. From the man page: fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline.
Return Value The strstr() function returns a pointer to the beginning of the first occurrence of string2 in string1. If string2 does not appear in string1, the strstr() function returns NULL. If string2 points to a string with zero length, the strstr() function returns string1.
All the const char * is telling you is that strstr is not going to modify the string you pass into it. Whether you modify the returned string or not is up to you as it is your string!
The strstr() function returns pointer to the first occurrence of the matched string in the given string. It is used to return substring from first match till the last character. Syntax: char *strstr(const char *string, const char *match)
When you run strstr($str, 2660)
the $needle
is resolved to the character "d" by calling chr(2660)
and therefore it stops at the first "d" found in the given $str
, in this case right at the 11th character.
chr(2660)
?Because when the $needle
is not a string strstr
casts that argument to an integer and uses the corresponding character for that position from the extended ASCII code where chr(2660)
is "d".
If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.
chr(2660)
return "d" when "d" is ord(100)
?Because values outside the valid range [0-255]
will be bitwise and'ed with 255
, which is equivalent to the following algorithm[source]
while ($ascii < 0) {
$ascii += 256;
}
$ascii %= 256;
So, 2660
becomes 100
, and then when passed to strstr
it's used as the ordinal value of the character and looks for character "d".
Confusing? Yes. I also expected it to be casted to a string, but that's what we get for assuming things in programming. This, at least, is documented; you'd be surprised the amount of times something weird happens and there's no official explanation to be found. At least not as easily as following the same link you provided.
strstr
?I did a little bit of research and found this gem (Rationale for
American National Standard
for Information Systems -
Programming Language -
C) from all the way back 1989 where they named all the functions relating to strings with the prefix str
which is logical, then since PHP's source is written in C it will explain why it has carried. My best guess is that we are searching for a string inside another string, they do say:
The strstr function is an invention of the Committee. It is included as a hook for efficient substring algorithms, or for built-in substring instructions.
strstr
chr
I think this answers your question:
needle
If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.
http://php.net/manual/en/function.strstr.php
Edit because of the comments:
chr(2660)
returns character d
, which is indeed in the haystack and that's why it won't return false as you expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With