Heim > Backend-Entwicklung > PHP-Tutorial > [科普小文章]php内核动态调试关于弱类型比较

[科普小文章]php内核动态调试关于弱类型比较

WBOY
Freigeben: 2016-06-20 12:26:37
Original
1009 Leute haben es durchsucht

0x00 前言

上期的三个白帽挑战题已经结束,但是大家依旧意犹未尽,讨论着 writeup 中的知识点,其中比较有意思的是关于php弱类型的:

array(0)>999999999
Nach dem Login kopieren

这个结果是true的。

群里各位大牛给了各种思考,和相关文章:

php.net/manual/zh/language.operators.comparison.php

但是基本都是别人给出的结论,我不太喜欢结论性的东西,这只让我知道了结果,并不知道为什么有这样的结果。

0x01 php动态调试(php5.6为例)

1.下载解压并安装

# wget http://cn2.php.net/distributions/php-5.6.0.tar.xz # xz -d php-5.6.0.tar.xz # tar vxf php-5.6.0.tar # cd php-5.6.0 # ./configure --enable-debug # make # sudo make install
Nach dem Login kopieren

2.相关文章推荐

《深入理解Zend执行引擎(PHP5)》

《使用vld查看OPCode》

《调式PHP源码》

0x02 OPCode分析

可以看出关键操作是IS_SMALLER,如果你仔细看过上面推荐文章就可以找到关键函数

ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
Nach dem Login kopieren

0x03 gdb动态调试

注意红框内容,相信看过上边内容的都能看懂(ps:详细内容太多,请先学习推荐文章)

大致逻辑是两个参数进来经过zendi_convert_scalar_to_number函数处理,由于我们一个是数组一个是整形,所以两个参数类型和值都不变

#define zendi_convert_scalar_to_number(op, holder, result) if (op==result) { if (Z_TYPE_P(op) != IS_LONG) { convert_scalar_to_number(op TSRMLS_CC); } } else { switch (Z_TYPE_P(op)) { case IS_STRING: { if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { ZVAL_LONG(&(holder), 0); } (op) = &(holder); break; } case IS_BOOL: case IS_RESOURCE: ZVAL_LONG(&(holder), Z_LVAL_P(op)); (op) = &(holder); break; case IS_NULL: ZVAL_LONG(&(holder), 0); (op) = &(holder); break; case IS_OBJECT: (holder) = (*(op)); zval_copy_ctor(&(holder)); convert_to_long_base(&(holder), 10); if (Z_TYPE(holder) == IS_LONG) { (op) = &(holder); } break; } }
Nach dem Login kopieren

然后再次进入循环到达

} else if (Z_TYPE_P(op1)==IS_ARRAY) { ZVAL_LONG(result, 1); return SUCCESS; } else if (Z_TYPE_P(op2)==IS_ARRAY) { ZVAL_LONG(result, -1); return SUCCESS;
Nach dem Login kopieren

从opcode可以看到op2为array(0)所以这儿返回-1

最后(Z_LVAL_P(result) < 0)成立,返回true

if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) { return FAILURE; } ZVAL_BOOL(result, (Z_LVAL_P(result) < 0)); return SUCCESS;
Nach dem Login kopieren

转载请注明来自 L.N.'s blog 的《[科普小文章]php内核动态调试关于弱类型比较》

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage