Php 什么是分析代码中不安全代码片段的好工具?

Php 什么是分析代码中不安全代码片段的好工具?,php,code-analysis,Php,Code Analysis,我正在寻找一些可以对PHP脚本进行基本测试的工具 这次我对复杂的测试解决方案不感兴趣,它需要为每一段代码编写测试。我对功能测试都不感兴趣 我希望此工具能够指出可能导致以下内容无效使用的代码片段: 变量 函数参数 函数返回值 无效用法可能是,例如,将NULL用作对象或数组,或将布尔值作为数组或对象(或NULL)所需的参数传递 此外,它还可能检查是否使用了“良好实践”,即,它可能警告使用if($condition)$doSomething是不安全的,如果它发现类似的东西 为了说明工具应该检测哪些代

我正在寻找一些可以对PHP脚本进行基本测试的工具

这次我对复杂的测试解决方案不感兴趣,它需要为每一段代码编写测试。我对功能测试都不感兴趣

我希望此工具能够指出可能导致以下内容无效使用的代码片段:

  • 变量
  • 函数参数
  • 函数返回值
  • 无效用法可能是,例如,将NULL用作对象或数组,或将布尔值作为数组或对象(或NULL)所需的参数传递

    此外,它还可能检查是否使用了“良好实践”,即,它可能警告使用
    if($condition)$doSomething是不安全的,如果它发现类似的东西


    为了说明工具应该检测哪些代码片段是“不安全的”,这里有两个示例

    在这种情况下,
    $filter
    可能是
    NULL
    ,但它被用作数组:

    <?php
        function getList(array $filter = null) { 
            $sql = '...';
            // ...
            foreach ( $filter as $field => $value ) {
                // ...
            }
            // ...
        }
    

    下面是相应的“安全”代码片段:

    // $filter is used only if it's non-empty; as list of arguments describes, it may be only NULL or array
    function getList(array $filter = null) { 
        $sql = '...';
        // ...
        if ( $filter ) {
            foreach ( $filter as $field => $value ) {
                // ...
            }
        }
        // ...
    }
    


    这不是基本的测试,但需要对令牌流进行非平凡的分析

    你可以使用

    扫描PHP源代码并查找潜在问题,如可能的bug、死代码、次优代码和过于复杂的表达式

    phpcs标记PHP、JavaScript和CSS文件,并检测违反已定义的一组编码标准的情况。它是一个重要的开发工具,可以确保代码保持干净和一致。它还可以帮助防止开发人员犯一些常见的语义错误

    或者——如果这还不够的话——用

    bytekit cli提供了一个命令行工具,它利用bytekit扩展在PHP字节码级别执行常见代码分析任务

    你将不得不为此写自己的嗅探

    其他工具和资源:


      • 一个好的IDE应该在开发过程中指出基本错误

        例如,我使用Netbeans,它突出显示了常见的代码错误,例如定义但未使用的变量,或者在if()条件下错误使用赋值运算符,其中等式运算符更为正常(即编写
        if($x=$y)
        而不是
        if($x=$y)

        类似这样的基本内容在Netbeans中出现,行号旁边有一个黄色的警告三角形。其他IDE将具有类似的特性


        我不认为它会指出您描述的具体错误情况,但它肯定会指出相当多的错误,甚至对于您提到的错误,我也希望在这里标记这些内容,而不是在一个单独的工具中。

        您需要的传统称为静态分析工具。这些工具经常做什么, 就是确定代码中的每个点,它知道关于变量的哪些事实 (在X=NULL之后,工具知道X为NULL),然后沿着各种控制流路径传播它所知道的,以查看变量的状态是否与操作不一致(例如,在发现X为NULL之后,查找必须执行的代码,该代码尝试将X作为数组访问)

        要做到这一点,您需要一个完整的PHP解析器,生成AST、至少告诉您PHP变量范围的符号表、确定控制和数据流的某种方法,以及检测各种编码错误的集合信息上的一组模式

        PHP的一个这样的工具是。它似乎可以做到这一点,你可以下载一个运行它(我没有具体的经验)。构建它的技术Stratego至少适合该任务;Stratego生产AST,可以从其中的各个地方收集事实,尽管我认为它在控制和数据流方面不是很好。这与另一个答案中提到的能够访问PHP令牌(如PHPC)的工具形成对比;仅从令牌计算控制和数据流是一场噩梦,实际上根本无法完成


        正确的机器似乎藏在Paul Biggar的机器里。不过,我似乎找不到任何迹象表明有人捡到了它并将其用作静态分析器的基础。

        使用
        调试回溯
        @diEcho,
        debug_backtrace()
        如何帮助测试整个系统的不安全代码?;)没有神奇的代码测试解决方案,更不用说能够分析或预测可能的控制流的工具了。如果您担心来自
        mysql\u free\u result()
        的警告,那么您可能应该避免,因为它是无引导的,或者添加语法盐。顺便说一句,这与安全无关。@mario,我不是在寻找“神奇的解决方案”。在我看来,这似乎是语言的一种基本用法。有一些IDE可以检测代码,比如
        if($str='something'){}
        ,那么为什么没有可以检测前面描述的代码片段的工具呢?关于安全-我不认为可能触发意外致命错误的代码总是安全的。@Gordon,对不起,还没有时间检查所有提到的工具。。。但我确实记得我问过这个问题,有一些答案,我也把这个问题添加到书签中,所以最终我会接受一些答案。对于“基本测试”,我指的是不需要编写几十个测试,也不知道系统功能需求的东西。谢谢你提供的工具名称-我稍后会看一看。@binaryLV如果你想实现你想实现的目标,你将编写比几十个测试多得多的代码。我想找到的是非常通用的,所以可能已经有人编写了。就像Spudley所写的,它甚至可以是IDE的一部分,其中一些已经在发现其他代码片段时发出通知。是的,我认为一个好的IDE应该是ab
        // $filter is used only if it's non-empty; as list of arguments describes, it may be only NULL or array
        function getList(array $filter = null) { 
            $sql = '...';
            // ...
            if ( $filter ) {
                foreach ( $filter as $field => $value ) {
                    // ...
                }
            }
            // ...
        }
        
        // $filter is forced to be an array
        function getList(array $filter = null) { 
            $filter = (array)$filter;
            $sql = '...';
            // ...
            foreach ( $filter as $field => $value ) {
                // ...
            }
            // ...
        }
        
        // if $res is false, mysql_fetch_assoc() and mysql_free_result() never executes
        $res = mysql_query('...');
        if ( $res === false ) {
            trigger_error('...');
            return;
        }
        while ( $row = mysql_fetch_assoc($res) ) {
            // ...
        }
        mysql_free_result($res);
        
        // if $res is false, mysql_fetch_assoc() and mysql_free_result() are skipped
        $res = mysql_query('...');
        if ( $res !== false ) {
            while ( $row = mysql_fetch_assoc($res) ) {
                // ...
            }
            mysql_free_result($res);
        }