php intval函数的特性

前言:php intval函数的特性笔记

参考文章:https://github.com/80vul/phpcodz/blob/master/research/pch-001.md
参考文章:https://zhuanlan.zhihu.com/p/146650526
参考地址:https://github.com/hoohack/read-php-src php7.1.9

intval函数特性

intval函数特性:直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时(\0)结束转换

intval函数定义在ext/standard/type.c 如下图所示

PHP_FUNCTION(intval)
{
	zval *num;
	zend_long base = 10;
	// 判断args个数,只能是1活着2 int intval( var,base),第二个参数转化对应的进制
	if (ZEND_NUM_ARGS() != 1 && ZEND_NUM_ARGS() != 2) {
		WRONG_PARAM_COUNT;
	}

	// 接受1个参数,最多接受2个参数
	ZEND_PARSE_PARAMETERS_START(1, 2)
		Z_PARAM_ZVAL(num) // 要intvla的值
		Z_PARAM_OPTIONAL
		Z_PARAM_LONG(base) // 第二个参数
	ZEND_PARSE_PARAMETERS_END();

	// 判断num的类型是否是字符串
	if (Z_TYPE_P(num) != IS_STRING || base == 10) {
		RETVAL_LONG(zval_get_long(num));
		return;
	}
	
        ....
        ....

	RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base));
}

这里继续跟进到zval_get_long函数中进行观察,可以看到先判断该op是否为long类型,这里传入是字符串显然不是,继续调用_zval_get_long_func(op)

static zend_always_inline zend_long _zval_get_long(zval *op) {
	return Z_TYPE_P(op) == IS_LONG ? Z_LVAL_P(op) : _zval_get_long_func(op);
}	

_zval_get_long_func(op)跟进去可以看到

ZEND_API zend_long ZEND_FASTCALL _zval_get_long_func(zval *op) /* {{{ */
{
	return _zval_get_long_func_ex(op, 1);
}

最后跟到_zval_get_long_func_ex中,可以看到对字符串的处理过程,主要是is_numeric_string函数

跟到is_numeric_string中可以发现,首字符的ascii是大于'9'的话那么直接返回0

如果是小于'9'的话的话则调用_is_numeric_string_ex处理,遍历字符如果是数字的话则继续遍历,或者是科学记数法

  • 数字的话则继续遍历

  • 科学记数法继续遍历

产生安全问题的代码

当intval用在if语句里面作为条件判断使用,将会导致这个判断失去意义,让其永远为真,从而可能产生安全问题

<?php
$var="1 union select 1,1,1 from admin";
if (intval($var))
	echo '$var='.$var;

posted @ 2020-04-07 15:44  zpchcbd  阅读(609)  评论(0编辑  收藏  举报