PHP и юникод в стрэктрейсе
12 марта 2012
Какое-то время назад creocoder наткнулся на ????? вместо значения параметра в логах ошибок Yii. После анализа проблемы стало ясно, что нашёлся баг в PHP.
Exception::getTraceAsString и Exception::__toString не работают с юникодом в значениях параметров при построении stacktrace. В результате для
function test($arg){ throw new Exception(); } try { test('тест'); } catch(Exception $e) { echo $e->getTraceAsString(); echo (string)$e; }
получаем
d:\web\usr\local\php54>php.exe d:\src\exception_wrong_trace\test.php
#0 D:\src\exception_wrong_trace\test.php(7): test('????')
#1 {main}exception 'Exception' in D:\src\exception_wrong_trace\test.php:3
Stack trace:
#0 D:\src\exception_wrong_trace\test.php(7): test('????')
#1 {main}
Обойти можно собрав строку руками на основе массива, полученного через Exception::getTrace.
В Yii пока решили это не фиксить. Заслал баг на php.net.



Комментарии RSS по email OK
Проблема очень старая на самом деле, но никогда не думал о ней как о баге....
Можно использовать $e->getTrace()
Проблема именно в преобразовании тейса в строку. ./Zend/zend_exceptions.c, метод _build_trace_args:
case IS_STRING: { int l_added; TRACE_APPEND_CHR('\''); if (Z_STRLEN_PP(arg) > 15) { TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15); TRACE_APPEND_STR("...', "); l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */ } else { l_added = Z_STRLEN_PP(arg); TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added); TRACE_APPEND_STR("', "); l_added += 3 + 1; } while (--l_added) { if ((*str)[*len - l_added] < 32) { (*str)[*len - l_added] = '?'; } } break; }О, может сразу в тикет отписаться?