Загадочный баг в ПХП
Во всех современных интерпретаторов вёдра багов, я обычно и внимания на них не обращаю, но свежезаведённый баг в ПХП какой-то забавный:
bolk@Bolk ~ $ php -r 'var_dump(0x0 + 2); var_dump(0x0+2); var_dump(0x0 +10);'
int(2)
int(4)
int(26)
Как видно, ПХП (у меня на 5.3.8 работает) считает сложение с шестадцатеричным нулём (обязательно слева и обязательно без пробела перед вторым слагаемым) какой-то интересной операцией.
С чем связано пока непонятно, я посмотрел какие токены выдаёт интерпретатор на парсинге, ничего подозрительного не увидел.
Добавлено позднее: с минусом тоже работает. Например «0x0 -10» даёт -26.
Добавлено ещё позднее: разобрался что это за интересная операция.
может он считает его указателем?
Комментарий для sunchaser.info:
Указателем на что?
Комментарий для Евгения Степанищева:
Судя по арифметике, на двухбайтовое значение + какое-то странное выравнивание после 10 смещений. есть смысл покопаться в коде
Комментарий для sunchaser.info:
Смысл покопаться в коде есть, но я бы не рискнул предположить что там не так, не глядя. Все числа до 10 умножаются на два, дальше какая-то каша, не пытался разобраться.
Комментарий для Евгения Степанищева:
с переходом на следующую 10-ку добавляется 8, дальше опять добавляется по 2
Комментарий для sunchaser.info:
Я назвал это «кашей» потому что знание о правиле «с переходом на следующую 10-ку добавляется 8, дальше опять добавляется по 2» не даёт ни понимания почему так происходит, ни сколько добавится при переходе с «0x0 +99» к «0x0 +100».
Я понял!
Так ребята, пишущие ПХП, заставляют ребят пишущих на ПХП правильно форматировать свой код!
Комментарий для Евгения Степанищева:
python-style?
Комментарий для sunchaser.info:
Посмотрел в код, вот что там происходит.
Когда ПХП встречает «0x…» он пропускает два байта («0x»), потом пропускает ведущие нули и передаёт остаток на конвертацию в функцию strtol (из stdlib). strtol применяется для преобразования строкового представления числа к long с указанным основанием системы счисления. ПХП вызывает её с параметром 16.
Ошибка в том, что не проверяется, что число не кончилось. В итоге в strtol попадает « +2», т. е. само число, которое переводится функцией strtol в шестнадцатеричный вид. Т. е. до десятки числа будут как бы умножаться на два, а дальше число будет складываться само с собой, но переведёным в шестнадцатеричный вид.
Например из десятки получится 26, так как складывается 10 + 0x10. Из сотни — 356 (100 + 0x100) и так далее.
Почему это работает только с пробелом не разбирался, спать пойду, завтра в Челябинск лететь ещё.
Комментарий для sunchaser.info:
Ага :)
тут у меня опечатка — «не проверяется, что число кончилось» должно быть.
Комментарий для Евгения Степанищева:
действительно,
исправляет багу
тогда там анализируется и преобразуется строка ’+’ (или ’-’), из которой получается 0
вот еще интересно:
код <ST_IN_SCRIPTING>{HNUM} {}
в 5.2 и 5.3 одинаковый
почему раньше это работало? :)
Что же заставило пэхапистов писать глючный лексический анализ самостоятельно... Буду надеяться что нечто серьёзное.
Комментарий для sunchaser.info:
Фиг его знает, разбираться уже лень :)
Комментарий для Павел Власов:
там bison / re2c стандартные, никаких костылей