Рассуждение за правилом ArrayIsStoredDirectly PMD - PullRequest
9 голосов
/ 23 июля 2010

PMD имеет правило ArrayIsStoredDirectly в наборе правил Sun Security:

Конструкторы и методы, получающие массивы, должны клонировать объекты и хранить копию. Это предотвращает влияние будущих изменений со стороны пользователя на внутренние функции.

Вот их пример:

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

Я не думаю, что полностью понимаю обоснование этого правила. Это потому, что значения в передаваемом массиве могут быть изменены где-то еще? Есть ли разница между передачей Collection и массива в отношении этого?

Ответы [ 3 ]

12 голосов
/ 23 июля 2010

Проблема в том, что вызывающая сторона может сохранить копию аргумента массива, который она передала, и затем может изменить его содержимое. Если объект критичен к безопасности и вызов сделан из ненадежного кода, у вас есть дыра в безопасности.

В этом контексте передача коллекции и ее сохранение без копирования также будет представлять потенциальную угрозу безопасности. (Я не знаю, есть ли правило PMD, чтобы сказать вам это.)

В обоих случаях способ устранения риска (если он реален) состоит в том, чтобы установить для атрибута копию массива аргументов или коллекции. С другой стороны, если вы знаете, что вызывающий код всегда будет доверенным кодом, его копия - пустая трата времени, и лучшим решением было бы сообщить PMD, чтобы он молчал об этом конкретном методе.

3 голосов
/ 23 июля 2010

Нет разницы между передачей коллекции или массива: в обоих случаях отправитель и получатель могут изменять содержимое структуры данных.Вот пример:

// ... 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 и сохранить ссылку на клон.Таким образом вы убедитесь, что ни один другой класс не содержит ссылку на ваш внутренний массив (если мы не забудем об отражении на мгновение и если мы не вернем этот внутренний массив в другом методе ...)

1 голос
/ 06 января 2012

Я думаю, что основная проблема с массивами заключается в том, что вы не можете контролировать доступ к нему.

Но с помощью объекта вы скрываете элементы за сеттерами, где вы можете контролировать, что будет установлено.Я думаю, что то же самое относится и к коллекциям, потому что вам нужно позвонить add() и toArray() вернуть копию.

...