【问题标题】:Reasoning behind ArrayIsStoredDirectly rule of PMDPMD的ArrayIsStoredDirectly规则背后的推理
【发布时间】:2010-07-23 05:36:37
【问题描述】:

PMD 在 Sun Security 规则集中有一个名为 ArrayIsStoredDirectly 的规则:

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

这是他们的例子:

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;
  }
}

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

【问题讨论】:

  • 在传递数组和集合方面没有区别。数组和集合的安全处理略有不同的是,对于数组,可以调用 .clone(),但您不应该信任 Collection 的 .clone() 方法。

标签: java security code-analysis pmd


【解决方案1】:

问题是调用者可能会保留它传递的数组参数的副本,然后可以更改其内容。如果对象对安全性至关重要,并且调用是从不受信任的代码中进行的,那么您就有了安全漏洞。

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

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

【讨论】:

  • 谢谢。我很困惑 PMD 抱怨直接设置数组而不是集合,并认为我可能在处理数组与集合方面缺少一些理解。
  • 我不认为传递集合会带来安全风险。因为如果您担心不受信任的代码,您可以使用不可变集合。但是原始数组不能是不可变的。
  • @gabe - 您需要考虑两种情况。 1)您将错误代码传递给集合并对其进行修改。 2) 错误的代码让你收集并在你背后修改它。传递 unmodifiable 集合可以防止 1) 而不是 2。(Java 中没有不可变的集合类...只有不可修改的...并且区别很大。)
【解决方案2】:

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

// ... 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 中克隆数组并存储对克隆的引用。这样你就可以确保没有其他类持有对你的内部数组的引用(除非我们暂时忘记反射,除非我们不在另一个方法中返回这个内部数组......)

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-09
      • 1970-01-01
      • 2018-02-06
      相关资源
      最近更新 更多