代码之家  ›  专栏  ›  技术社区  ›  Wilhelm Kleu

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

  •  9
  • Wilhelm Kleu  · 技术社区  · 15 年前

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

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

    以下是他们的例子:

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

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

    3 回复  |  直到 10 年前
        1
  •  12
  •   Stephen C    15 年前

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

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

    在这两种情况下,解决风险(如果风险是真实的)的方法是将属性设置为参数数组或集合的副本。另一方面,如果您知道调用者总是可信的代码,那么复制是在浪费时间,一个更好的解决方案是告诉PMD不要谈论这个特定的方法。

        2
  •  3
  •   Andreas Dolk    15 年前

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

    // ... 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
  •  1
  •   n3utrino    13 年前

    我认为数组的主要问题是 不能 控制对它的访问。

    但有了一个对象,你就把成员隐藏在setter后面, 可以 控制将要设置的内容。我认为这同样适用于托收,因为你需要打电话 add() toArray() 返回一个副本。