声纳违规:安全 - 数组直接存储

时间:2012-07-20 14:02:03

标签: java sonarqube

声纳违规行为:

声纳违规:安全 - 数组直接存储

public void setMyArray(String[] myArray) { 
  this.myArray = myArray; 
} 

解决方案:

public void setMyArray(String[] newMyArray) { 
  if(newMyArray == null) { 
    this.myArray = new String[0]; 
  } else { 
   this.myArray = Arrays.copyOf(newMyArray, newMyArray.length); 
  } 
}

但我想知道为什么?

7 个答案:

答案 0 :(得分:51)

它抱怨你存储的数组与调用者持有的数组相同。也就是说,如果调用者随后修改了这个数组,那么存储在对象中的数组(以及对象本身)将会改变。

解决方案是在传递对象时在对象中制作副本。这称为防御性复制。集合的后续修改不会影响存储在对象中的数组。

通常在返回集合时(例如在相应的getMyArray()调用中)执行此操作也是一种好习惯。否则,接收方可以执行修改并影响存储的实例。

请注意,这显然适用于所有可变集合(实际上是所有可变对象) - 而不仅仅是数组。另请注意,这会产生性能影响,需要与其他问题一起进行评估。

答案 1 :(得分:21)

这叫做防御性复制。关于这个主题的一篇很好的文章是Brian Goetz的"Whose object is it, anyway?",它讨论了getter和setter的值和引用语义之间的区别。

基本上,引用语义(没有副本)的风险是你错误地认为你拥有数组,当你修改它时,你也修改了具有数组别名的其他结构。您可以在线找到有关防御性复制和与对象别名相关的问题的许多信息。

答案 2 :(得分:12)

我有同样的问题:

  

安全性 - 数组直接存储用户提供的数组   'palomitas'直接存储。

我原来的方法:

public void setCheck(boolean[] palomitas) {
        this.check=palomitas;
    }

修正转向:

public void setCheck(boolean[] palomitas) { 
      if(palomitas == null) { 
        this.check = new boolean[0]; 
      } else { 
       this.check = Arrays.copyOf(palomitas, palomitas.length); 
      } 
}

其他例子:

  

安全性 - 数组直接存储用户提供的数组

private String[] arrString;

    public ListaJorgeAdapter(String[] stringArg) {      
        arrString = stringArg;
    }

修正:

public ListaJorgeAdapter(String[] stringArg) {  
    if(stringArg == null) { 
      this.arrString = new String[0]; 
    } else { 
      this.arrString = Arrays.copyOf(stringArg, stringArg.length); 
    } 
}

答案 3 :(得分:3)

要消除它们,你必须在存储/返回它之前克隆数组,如下面的类实现所示,所以没有人可以修改或获取你的类的原始数据,但只能复制它们。

public byte[] getarrString() {
    return arrString.clone();
}
/**
 * @param arrStringthe arrString to set
 */
public void arrString(byte[] arrString) {
    this.arrString= arrString.clone();
}

我这样使用它现在我没有得到任何SONAR违规......

答案 4 :(得分:2)

比这更容易。您只需要将方法参数重命名为其他任何内容,以避免Sonar违规。

http://osdir.com/ml/java-sonar-general/2012-01/msg00223.html

public void setInventoryClassId(String[] newInventoryClassId)
    {                
            if(newInventoryClassId == null)
            {
                    this.inventoryClassId = new String[0];
            }
            else
            {
                    this.inventoryClassId = Arrays.copyOf(newInventoryClassId, newInventoryClassId.length);
            }

    } 

答案 5 :(得分:0)

采取防御性实施方式可以为您节省大量时间。 在Guava中,您可以获得另一个很好的解决方案来实现目标:ImmutableCollections

http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained

答案 6 :(得分:0)

在某些情况下,这是一个设计决定而不会错过。在这些情况下,您需要修改声纳规则以将其排除,以便它不会在报告中显示此类问题。