配置流分析深度

流分析通过分析的代码构建路径来检测不同类型的问题。鉴于可能无法分析整个应用程序中的所有路径,您可以设置所需的分析深度级别。更深入的分析会报告更多任务,但对性能有一定影响,内存消耗也会略有增加。

您可以使用 DTP 中的测试配置界面来指定分析的深度。前往报告中心> 测试配置> 静态分析> 流分析高级设置> 性能> 深度分析并选择以下选项之一:

流分析深度默认设置为标准

设置超时策略

除了分析的深度,流分析还利用额外的超时保护来确保分析在合理时间内完成。使用 DTP 中的测试配置界面可以设置合适的策略。前往报告中心> 测试配置> 静态分析> 流分析高级设置> 性能> 超时策略并选择以下选项之一:

默认的超时选项是时间,值设置为 60 秒。要获取有关分析期间发生的流分析超时的信息,可查看分析后生成报告中的设置问题部分。

在启用分析数据交换的情况下运行流分析

在此模式下,分析数据将写入磁盘。分析数据交换使用相同的持久存储,与增量分析的过程类似。如果对大型项目运行分析,那么代表着所分析源代码语义模型的分析数据可能会消耗用于运行流分析的所有内存。若发生这种情况,流分析将从内存中删除部分当前不需要的分析数据,之后再从磁盘中重新读取。

一般而言,我们建议在配置了 Xmx JVM 选项的大型 JVM 堆中运行Jtest。这样做是为了最大限度减少交换,从而提高性能。如果内存足够,则可以禁用分析数据交换以加快代码分析速度。

您可以使用 DTP 中的测试配置界面来启用或禁用该模式:

允许将分析数据交换到磁盘: 默认启用 。如果对不需要大量内存的中小型项目运行流分析,或者在内存充足的情况下(例如,对于 64 位系统),可以禁用此选项来加快分析速度。

配置流分析详细度

您可以使用 DTP 中的测试配置界面来配置以下选项:

指定 null 检查方法

Null-checking 方法选项允许您指定将空参数传递给方法时的期望返回值。这可以减少误报和冗余路径(当空变量的返回值未知时通常会构建这些路径)的产生。

选择已启用复选框并提供以下信息:

null 检查方法示例

流分析会对分析范围内的方法进行分析。当方法超出当前分析范围(例如第三方库)时,需要进行 null 检查方法参数化。以下示例中的类定义在不同的程序集中,并且超出了分析范围(UString)。该类使用静态方法以多种方式操作包含 Java 字符串的代码,包括 UString.isEmptyOrNull(字符串),其定义为:

public class UString
{
    static boolean isEmptyOrNull(String variable)
    {
        if ((variable == null) || (variable.length() == 0)) {
            return true;
        }
        return false;
    }
}

下面的类由流分析的 BD-EXCEPT-NP 规则进行分析:

public class SomeClass
{
    void someMethod(String variable)
    {
        boolean flag = variable == null; // violation search starts here
        if (UString.isEmptyOrNull(variable)) {
            /** 
             * In case variable is null, we will always get to this branch of the if clause.
             */
            System.out.println("String is empty");
        } else {
            variable.toString(); // FALSE POSITIVE BD-EXCEPT-NP VIOLATION
        }
    }
}

流分析假设 isEmptyOrNull() 方法的返回值未知。这是因为该方法不在分析范围内。流分析将分析 if 语句的 thenelse 分支,并在其中一个语句中发现违规。但是,当变量为空时,调用此方法会返回 true。

UString.isEmptyOrNull() 添加到 null 检查方法的参数化列表中并指定返回值后,如果跟踪的变量被传递给该方法,流分析将不会报告违规。因为这样就不会分析 if 语句的错误分支,从而避免误报。

null 检查方法限制

添加到此参数化列表中的方法应该是具有原始 boolean 返回值的静态方法。该限制是为了避免参数化过于复杂,并确保不存在可能影响 null 检查方法结果的其他变量。 

指定资源

资源选项卡用于定义 BD.RES 分类(资源)规则应该检查哪些资源。这些规则检查在此选项卡上定义和启用的所有资源是否正确使用。

  1. 指定资源类型。
  2. 选择已启用复选框。
  3. 如果合适/需要,禁用不要在应用程序终止时报告违规行为选项。
  4. 点击箭头展开资源分配器资源关闭器选项卡,并完成表格中分配器和关闭器的相关信息。下面提供了有关完成这些选项卡的详细信息。

配置资源分配器

资源分配器表格可以用能够产生资源的方法的描述符来设置。该表格包含以下列:

分配方法返回表示分配失败的错误码十分常见。当分配方法返回一个资源时,NULL 值通常表示分配失败。流分析在寻找资源泄漏时需要了解分配是否成功;这有助于只报告实际发生分配的路径中缺失的释放方法调用。在资源分配器方法返回一个资源的情况下,如果返回值不为 NULL,则流分析假设资源已成功分配。

配置资源关闭器

资源关闭器表格可以用能够关闭资源的方法的描述符来设置。该表格包含以下列:

指定始终要分析的方法

总是要分析的方法选项用于定义在执行路径中遇到时始终会被分析的方法。这有助于确保规则在检查特定路径时,会分析通常不会检查的方法。

选择启用复选框并在表格中输入以下信息:

指定污染方法参数的 Spring 注解

污染了方法参数的 Spring HTTP 请求注释选项用于配置会污染一个或多个方法参数的 Spring 注解。此选项仅影响 BD.SECURITY 分类中包含‘受污染数据来源’参数的规则,并且该参数已配置为将来自‘Spring http 请求’的数据视为受污染数据。

您可以在以下表格之一配置注解:

这些表格包含以下列:

指定注入注解

注入注解选项用于定义针对注入的注解。因此,如果字段或 setter 方法带注解,流分析将不会认为字段值未初始化或为空。

该表格包含以下列:

分析使用 Spring 框架的项目

分析使用 Spring 框架的项目不需要额外的配置。流分析能够自动识别 Spring 框架特性,并调整报告的违规以提供准确的结果。

以下部分详细介绍了流分析如何处理该框架功能以及对流分析规则违规报告的影响。

处理自动初始化的字段

流分析可以识别用于 Spring 注入的注解,这些注解会自动初始化带注解的字段。如果某个字段带注解,流分析将不会认为字段值未初始化或为空。这可以防止以下规则误报:

您可以查看自动初始化字段的默认注入注解列表,或通过修改测试配置(静态分析设置> 控制反转 (IOC) 框架设置)来自定义该列表。

处理控制器类

流分析可以识别使用了 Spring 控制器类和 HTTP 请求处理方法的情况。因此:


(info) 流分析假定 Java Validation API 不足以确保正确验证受污染的数据。Java Validation 通常用于验证从外部源获取的数据,而在特定上下文中使用受污染数据前必须进行适当的清理。这意味着,要确保正确的验证,需要根据数据是被传入 SQL 查询语句还是嵌入到 HTTP 响应中来选择不同的验证方法。

识别受污染的数据源

流分析可以识别潜在受污染数据的 Spring 特定来源。在未经验证的情况下将以下来源的数据传递给危险方法时,检测受污染数据的流分析规则会报告违规:

指定 Spring HTTP 请求注解

对于假设 Spring http 请求是潜在被污染数据来源的规则,您可以指定会污染方法中一个或多个参数的 Spring 注解;详细信息,请参阅指定污染方法参数的 Spring 注解

指定可以在测试范围外重写虚方法

为确保流分析识别出指定的虚方法可在测试范围外重写,需在该方法的 Javadoc 注释中添加 @jtest.canBeOverriden

例如以下代码: 

public abstract class Test
{
    protected boolean get()
    {
        return true;
    } 
     void foo(Test test)
    {
        if (test.get()) {} // BD.PB.CC VIOLATION
    }
}

如果流分析未发现 Test 类中 get 方法的其他实现(重写该方法且可能返回 false),则会假定 get 方法始终返回 true,并会报告 BD.PB.CC 违规。

但是,继承 Test 类并重写 get 方法的类可以不在测试范围内。在该情况下,可以提供 @jtest.can beoverriden Javadoc 标记,这样流分析就会知道可能存在其他重写实现。

public abstract class Test
{
    /**
     * @jtest.canBeOverriden
     */
    protected boolean get()
    {
        return true;
    } 
    void foo(Test test)
    {
        if (test.get()) {} // BD.PB.CC NO VIOLATION
    }
}

在该情况下,不会报告 BD.PB.CC 违规。