PMD has a rule called ArrayIsStoredDirectly in the Sun Security ruleset:
Constructors and methods receiving arrays should clone objects and store the copy. This prevents that future changes from the user affect the internal functionality.
Here is their example:
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;
}
}
I don't think I completely understand the reasoning behind this rule. Is it because the values in the array passed can be altered somewhere else? Is there a difference between passing a Collection vs passing an array in regards to this?
The problem is that the caller may keep a copy of the array argument that it passed, and can then change its contents. If the object is security critical and the call is made from untrusted code, you've got a security hole.
In this context, passing a collection and saving it without copying it would also be a potential security risk. (I don't know if there's a PMD rule to tell you this.)
In both cases, the way to address the risk (if it is real) is to set the attribute to a copy of the argument array or collection. On the other hand, if you know that the caller is always going to be trusted code, the copy is a waste of time, and a better solution would be to tell PMD to be quiet about that particular method.
There is no differnce between passing a collection or an array: in both cases sender and receiver can modify the content of the datastructure. Here's an example:
// ... 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"}
If you do not want this behaviour, you have to, following this PMD rule, clone the array in Foo and store a reference to the clone. This way you make sure, that no other class holds a reference to your internal array (unless we forget about reflection for a moment and unless we don't return this internal array in another method...)
I think the main problem with arrays is that you can not control acces to it.
But with a Object you hide members behind setters where you can control what will be set. I think the same applies to Collections because you need to call add()
and toArray()
returns a copy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With