Java PMD阵列存储直接规则背后的推理

Java PMD阵列存储直接规则背后的推理,java,security,code-analysis,pmd,Java,Security,Code Analysis,Pmd,PMD在Sun安全规则集中有一个名为Arrayistoreddly的规则: 接收数组的构造函数和方法应该克隆对象并存储副本。这可以防止用户将来的更改影响内部功能 以下是他们的例子: public class Foo { private String [] x; public void foo (String [] param) { // Don't do this, make a copy of the array at least this.x=param;

PMD在Sun安全规则集中有一个名为Arrayistoreddly的规则:

接收数组的构造函数和方法应该克隆对象并存储副本。这可以防止用户将来的更改影响内部功能

以下是他们的例子:

public class Foo {
 private String [] x;
  public void foo (String [] param) {
      // Don't do this, make a copy of the array at least
      this.x=param;
  }
}

我不认为我完全理解这条规则背后的原因。是否因为传递的数组中的值可以在其他地方更改?在这方面,传递集合和传递数组之间有区别吗?

传递集合和数组之间没有区别:在这两种情况下,发送方和接收方都可以修改数据结构的内容。下面是一个例子:

// ... in some method
Foo myfoo = new Foo();
String[] array = {"One", "Two", "Three"};
myfoo.foo(array);     // now the Foo instance gets {"One", "Two", "Three"}

array[1] = "Changed"; // now the internal field x in myfoo is {"One", "Changed", "Three"}

如果不希望出现这种行为,则必须遵循此PMD规则,在Foo中克隆阵列并存储对克隆的引用。通过这种方式,您可以确保没有其他类持有对内部数组的引用(除非我们暂时忘记了反射,并且除非我们没有在另一个方法中返回此内部数组…)

问题是调用方可能保留它传递的数组参数的副本,然后可以更改其内容。如果对象是安全关键的,并且调用是由不受信任的代码进行的,则存在安全漏洞

在这种情况下,传递一个集合并保存它而不复制它也是一种潜在的安全风险。(我不知道是否有PMD规则告诉您这一点。)


在这两种情况下,解决风险的方法(如果是真实的)是将属性设置为参数数组或集合的副本。另一方面,如果您知道调用方始终是受信任的代码,则复制是浪费时间,更好的解决方案是告诉PMD对该特定方法保持沉默。

我认为数组的主要问题是您无法控制对它的访问


但对于对象,您将成员隐藏在setter后面,在那里您可以控制将要设置的内容。我认为这同样适用于集合,因为您需要调用
add()
,并且
toArray()
返回一个副本。

传递数组与集合没有区别。安全处理数组和集合的一个细微区别是,对于数组,可以调用.clone(),但不应该信任集合的.clone()方法。谢谢。我感到困惑的是,PMD抱怨的是直接设置数组,而不是集合,我认为我可能对数组与集合的处理缺乏一些了解。我不认为传递集合会有安全风险。因为如果您担心不受信任的代码,您可以使用不可变的集合。但是原始数组不能是不可变的。@ Gabe-有两种情况需要考虑。1) 您将错误代码传递给集合,它将对其进行修改。2) 错误的代码会将集合传递给您,并在背后修改它。传递不可修改的集合可以防止1)而不是2。(Java中没有不可变的集合类…只有不可修改的集合类…差别很大。)