从php内核视点剖析php弱类型

在CTF竞赛中PHP弱类型的特性常常被用上,但咱们往往知其然不知其所以然,终究为什么PHP是弱类型呢?很少人深究。在这次源码剖析的过程中我收成很大,第一次学会了怎么深化了解一个问题,尽管花...

在CTF竞赛中PHP弱类型的特性常常被用上,但咱们往往知其然不知其所以然,终究为什么PHP是弱类型呢?很少人深究。在这次源码剖析的过程中我收成很大,第一次学会了怎么深化了解一个问题,尽管花费了我许多时刻,但这能够说是一段十分值得的阅历。
 
正文
首要引进一个问题,为什么以下结果是恒为真的呢?
var_dump([]>1);
var_dump([]>0);
var_dump([]>-1);
当然实践ctf中问题可能会如下
$_GET[Password]>99999;
当传入Password[]=1
时侯恒为真
当然再换一种办法
var_dump([[]]>[1]);
仍旧是恒为真
关于这类问题,许多人都是以为PHP由于它是弱类型言语它就有这种特性
那么为什么PHP会有这种特性呢?
咱们首要查阅下PHP手册
http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.types

在手册中写到,当array和anything进行比较的时分array is always greater
这是一种PHP的界说。
那么终究PHP终究在哪界说了这种特色呢?
咱们仍旧不知道。
咱们再抛出个问题终究什么是PHP弱类型呢?
许多人可能会答复弱类型便是弱类型,当传入Password[]=1就会绕过这便是弱类型
这种答复肯定是不稳当的
具体弱类型界说
PHP是弱类型言语,不需求清晰的界说变量的类型,变量的类型依据运用时的上下文所决议,也便是变量会依据不同表达式所需求的类型主动转化,比方求和,PHP会将两个相加的值转为long、double再进行加和。每种类型转为别的一种类型都有固定的规矩,当某个操作发现类型不符时就会依照这个规矩进行转化,这个规矩正是弱类型完结的根底。
咱们再经过查阅PHP源码来深刻了解PHP弱类型的特色
PHP是开源的一种言语,咱们在Github上能够很简略的查询到它的源码
传送门
这儿找函数会便利点
当然解说下什么是Zend
Zend是PHP言语完结的最为重要的部分,是PHP最根底、最中心的部分,它的源码在/Zend目录下,PHP代码从编译到履行都是由Zend完结的
至于为什么要查询zend_operators.h这个文件,operator操作符,其他几个文件不像存在比较函数,有的时分查源码时分便是需求靠感觉,这种大项目 函数变量什么的都有标准 一般所见即所得 看懂英语就大约猜得到用处的,
当然这个文件也不一般
我再进行解说下,当然想深化了解能够看这儿
PHP在内核中是经过zval这个结构体来存储变量的,它的界说在Zend/zend.h文件里,简略精粹,只要四个成员组成:
咱们定位到函数
ZEND_API int ZEND_FASTCALL is_smaller_function(zval result, zval op1, zval *op2);
这儿传入了两个值op1,op2,传出一个result
解说下zval类型
zval以一个P完毕的宏的参数大多是zval型变量。 此外获取变量类型的宏还有两个,分别是Z_TYPE和Z_TYPE_PP,前者的参数是zval型,而后者的参数则是*zval。
这样说可能会有些笼统
咱们换种办法解说,当再php源码中要想判别一个变量的类型最直接的办法,比方想判别这个变量是否为空
变量->type == IS_NULL
这种办法尽管是正确的,但PHP官网并不主张这么做,PHP中界说了很多的宏,供咱们检测、操作变量运用
解说下什么是宏
C言语中答应用一个标识符来标识一个字符串,称为“宏”;标识符为“宏名”。在编译预处理时,对程序中所有呈现的“宏名”,都用宏界说时的字符串去代换,简称“宏代换”或“宏打开”。一般办法:#define 宏名 字符串
宏界说阐明及留意:
宏界说时用宏名来表明一个字符串,在宏打开时又以该字符串替换了宏名,这仅仅一个简略的替换;宏界说不需求再行末加分号,若加上分号,则会连分号也会被替换的;宏界说必须在函数外面;宏界说的效果域:从界说指令至程序完毕,若想停止宏的效果域,则运用undef指令;宏名在程序顶用引号括起来,则预处理程序对其不进行宏替换;宏界说是能够嵌套运用的,在打开时,由预处理程序层层替换;主张在进行宏界说时,尽量运用大写字母表明宏名;可用宏来表明数据类型,使书写便利;对“输出格局”做用界说,能够削减书写费事。
PHP主张运用的办法
Z_TYPE_P(变量) == IS_NULL
以一个P完毕的宏的参数大多是zval型变量。 此外获取变量类型的宏还有两个,分别是Z_TYPE和Z_TYPE_PP,前者的参数是zval型,而后者的参数则是*zval
这样咱们便能够猜想一下php内核是怎么完结gettype这个函数了,代码如下:想要具体了解的能够看这儿
//开端界说php言语中的函数gettype
PHP_FUNCTION(gettype)
{
    //arg直接指向调用gettype函数时所传递的参数。是一个zval**结构
    //所以咱们要对他运用__PP后缀的宏。
    zval **arg;
    //这个if的操作主要是让arg指向参数~
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
        return;
    }
    //调用Z_TYPE_PP宏来获取arg指向zval的类型。
    //然后是一个switch结构,RETVAL_STRING宏代表这gettype函数回来的字符串类型的值
    switch (Z_TYPE_PP(arg)) {
        case IS_NULL:
            RETVAL_STRING("NULL", 1);
            break;
        case IS_BOOL:
            RETVAL_STRING("boolean", 1);

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]  黑客接单网

  • 发表于 2021-04-08 11:36
  • 阅读 ( 2 )
  • 分类:生活经历

0 条评论

请先 登录 后评论
挑剔的姐姐
挑剔的姐姐

9 篇文章

你可能感兴趣的

相关问题