9 ms·
I'm not exactly clear on how PHP == works, but you can see the MD5 for yourself: $ echo -n 240610708 | md5sum 0e462097431906509019562988736854 - $
by dietrichepp 11y ago
I'm not exactly clear on how PHP == works, but you can see the MD5 for yourself:
$ echo -n 240610708 | md5sum
0e462097431906509019562988736854 -
$ echo -n QNKCDZO | md5sum
0e830400451993494058024219903391 -
$ echo -n aabg7XSs | md5sum
0e087386482136013740957780965295 -
All of them start with 0e, which makes me think that they're being parsed as floats and getting converted to 0.0. This is why "magic" operators like == in PHP and JavaScript never should have existed in the first place. Operators like == should be, by default, extremely boring. PHP's just happens to be a bit more magical even than JavaScript's.
- sigsergv 11y agoYou're right: % php -r 'var_dump("0e1" == "0e2");' bool(true)
- lars 11y agoThis, combined with the fact that you can increment strings gives some 'interesting' results: $a = "2d9"; $a++; echo $a . "\n"; $a++; echo $a . "\n"; Output 2e0 3
- ulrikrasmussen 11y agoThis is wonderful, I love it! Interestingly [1], this echoes "2e0" followed by "3" in hhvm-3.7.0, but "3" followed by "4" in hhvm-3.6.0. [1] http://3v4l.org/sJhP8 http://3v4l.org/sJhP8
- debacle 11y agoThat means that someone was using this "feature" in a relatively core piece of code from the PHP ecosystem. Enough that hhvm felt they needed to support it.
- jlouis 11y agoThere is some nasty type conversion going on here, from the type of stochastic random throws of two nine-sided dice to floats to integers. Where is your type preservation, PHP?
- jlouis 11y agoThere is some nasty type conversion going on here, from the type of stochastic random throws of two nine-sided dice to floats to integers. Where is your type preservation, PHP?
- marcofiset 11y agoWho tries to increment strings anyway? What is your point here?
- pionar 11y agobecause PHP is dynamically typed, it's easier to accidentally increment a string.
- deleted 11y ago[deleted]
- mikeash 11y agoGiven how happy PHP is about converting strings to integers on demand, it would be pretty easy to take string input intended to be a number, forget to actually convert it, and go around using it happily until one day you accidentally set off a bomb.
- BasDirks 11y agoYeah, who would do that? Nobody. So why the _ is it possible in the first place?
- Someone1234 11y agoIs there any way to defend against this one? I know === to turn off type conversion with the equality operator, but what about here?
- digitalzombie 11y agoIf condition check type and not try to increment a string... if (!is_string($notstr)) ++$notstr; edit: I think checking for integer is better, if it's just incrementing integer. I was going to say type hinting but I just realized php's primitive cannot be type hinted.
- VMG 11y agoSame goes for the `0E` prefix with an uppercase E The likelihood of generating a hash value with that kind of prefix is 2 in 65536. Finding a collision `hash(a) == hash(b)` with this "weak" equality comparison is approximately 1 in 256 if I'm not mistaken.
- masklinn 11y ago> The likelihood of generating a hash value with that kind of prefix is 2 in 65536. The prefix is not sufficient though, the suffix must be entirely decimal otherwise it's not a valid number in scientific notation.
- dietrichepp 11y agoThe prefix is sufficient. Any hash matching /0e[0-9].*/ works.
- masklinn 11y agoAs far as I can see the prefix is not sufficient, a single non-digit character in the tail fails the conversion (and the equality check): http://3v4l.org/ctASF http://3v4l.org/ctASF (vs http://3v4l.org/5FvJu http://3v4l.org/5FvJu, exact same strings but for the last character replaced by a digit)
- userbinator 11y agoWhich means the probability of generating a hash value of the form 0[eE][0-9]{30} is (1/128)(10/16)^30 or 5.9e-9. It certainly reduces the strength of the hash (and MD5 shouldn't be used anymore in any case), but still a roughly 6 in a billion chance of someone choosing e.g. a password and it happening to be exploitable in this manner.
- dietrichepp 11y agoYou are mistaken: my guess is that you are taking the square root because of the birthday paradox, but that is incorrect, and the birthday paradox does not apply here anyway. The probability of generating a hash with the right prefix is 10 in 16^3, or about 0.25%. Finding a 0e... == 0e... collision has probability ~6e-6, if both inputs are random. The chance that two hashes collide in this way given N random inputs is 1-(1-p)^(N-1), for N>0.
- DoubleMalt 11y agoOnce I wrote a little PHP application to manage a clan in a browser game. I used an MD5 hash as session id that I checked with if(session_id) When users started reporting that their logins would sometimes not work at the first time, I found out that strings that start with zero are coerced to 0 and then interpreted as false. Never used PHP for anything important since.
- rimantas 11y agoYeah, documentation is for pussies.
- imakesnowflakes 11y agoHere is one PHP core developer claiming that PHP documentation is wrong, even on fundamental things... http://www.reddit.com/r/lolphp/comments/2md8c0/new_safe_casting_function_rfc_casting_10_to/cm3dpdj http://www.reddit.com/r/lolphp/comments/2md8c0/new_safe_cast... Just saying....
- deleted 11y ago[deleted]
- sarciszewski 11y ago> I used an MD5 hash as session id > Never used PHP for anything important since. The problem here isn't PHP, the problem here is you.
- FractalNerve 11y agoI tried replacing == with === and it gave me bool(false) in all cases. Here's the code: http://3v4l.org/15hr7 http://3v4l.org/15hr7
- maw 11y agoI don't think I'd use the word "magic" here, because it implies that == works when, by any reasonable standard, it does not.
- kyllo 11y agoAhh PHP, the language where true == false php > if ((true == "foo") && ("foo" == 0) && (0 == false)) echo "yay!"; yay!
- jakcst 11y agoThis truly just bummed me out :(
- Navarr 11y agoDon't let it - he understands exactly how the types are being converted in order to make it appear that true == false. This sort of thing happens in type conversion languages. You can either use === to stop conversion or you can understand how conversion works. I'm not sure how the order of conversions is decided by PHP, but here's a brief explanation: Compare "foo" to true. Convert the string "foo" to a boolean value. As it is desirable that a non-empty string evaluate to true, we will say they are "equal." Compare "foo" to 0. Convert the string "foo" to a numeric value. As "foo" does not start with 0x it cannot be hex, and as it does not start with 0 it cannot be octal, so evaluate it as decimal - there are no numbers before the first letter so the string foo, when numerical, is 0. Evaluate 0 to false. Well, that's just binary now isn't it? Of course false and 0 are equal! The moral of the story, == is not "exactly equal" it is "relatively equal."
- kyllo 11y agoThe problem with designing a language that does these sorts of implicit type conversions is that the "equality" operator violates the fundamental properties of equality. Since grade school mathematics we are all taught that equality is symmetric and transitive, and PHP's == operator is neither.
- spdionis 11y agoAFAIK == is always symmetric.
- Nemcue 11y ago
- protomyth 11y agoSo, you should use the old shell trick of adding an "X" to the front of the strings before comparing?
- maxlybbert 11y agoOr use === instead of ==. The PHP developers have been pretty honest about the mistakes they made early on because they didn't know better. Unfortunately, many of those mistakes persist. The difference between == and === is one of the more well-known mistakes.
- redthrowaway 11y agoType coercion is fine so long as you recognize it as the syntactic sugar that it is. JS and PHP support easy type coercion because HTTP is string-only and it would be a pain in the ass to explicitly cast every value you get over the wire. You just have to be sure that, when you use it, you do so intentionally and not out of laziness.
- steego 11y agoHere's what I took away:: It's pain in the ass to validate and sanitize your input.