2012-07-20 22 views
59

Hay una Violación Sonar:Sonar Violación: Seguridad - matriz se almacena directamente

Sonar Violación: Seguridad - matriz se almacena directamente

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

Solución:

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

Pero me pregunto por qué?

+10

Um ... esa solución no funcionó para mí, en realidad. Sonar todavía lo recoge y se queja de él, a pesar de hacer una copia. – ndtreviv

+1

@ndtreviv entonces, ¿cómo lo resolvió? – sakura

+2

@ndtreviv: Estaba teniendo este problema también, y este error no desaparecerá si el nombre de la variable local suministrada al método es el mismo que la variable de instancia que está almacenando. Asegúrese de que sean diferentes, y la solución anterior debería funcionar. Encontré esto a través del siguiente [enlace] (http://sonarqube.15.x6.nabble.com/Security-Array-is-stored-directly-weirness-td3632714.html) – Matt

Respuesta

52

Se queja de que la matriz que está almacenando es la misma que tiene la persona que llama. Es decir, si la persona que llama posteriormente modifica esta matriz, la matriz almacenada en el objeto (y, por lo tanto, el objeto mismo) cambiará.

La solución es hacer una copia dentro del objeto cuando se pasa. Esto se llama copiando a la defensiva. Una modificación posterior de la colección no afectará a la matriz almacenada dentro del objeto.

También es una buena práctica hacerlo normalmente al devolver una colección (por ejemplo, en una llamada correspondiente getMyArray()). De lo contrario, el receptor podría realizar una modificación y afectar la instancia almacenada.

Tenga en cuenta que esto obviamente se aplica a todas las colecciones mutables (y, de hecho, a todos los objetos mutables), no solo a las matrices. Tenga en cuenta también que esto tiene un impacto en el rendimiento que debe evaluarse junto con otras preocupaciones.

+0

Puedo ver el motivo ... ¿Qué pasa si deliberadamente quiero que la persona que llama y su destino tengan la misma copia? –

+2

Esa es una decisión de diseño. Pero creo que es importante entender * quién * posee esta información y cómo (si es necesario) informa a los objetos que la contienen que ha cambiado. Es bastante razonable en un conjunto de componentes estrechamente relacionados para pasar colecciones sin copia defensiva. Pero en algún momento habrá un límite en el que tendrá que protegerse (por ejemplo, conectándose a un tercer código de cliente o pary) –

+1

seguramente el OP * está * haciendo una copia defensiva con 'this.myArray = Arrays.copyOf (newMyArray, newMyArray.length); '? – Qwerky

22

Se llama copiado defensivo. Un buen artículo sobre el tema es "Whose object is it, anyway?" de Brian Goetz, que analiza la diferencia entre el valor y la semántica de referencia para getters y setters.

Básicamente, el riesgo con la semántica de referencia (sin una copia) es que piensas erróneamente que eres el propietario de la matriz, y cuando la modificas, también modificas otras estructuras que tienen alias para la matriz. Puede encontrar mucha información sobre copias defensivas y problemas relacionados con el alias de objetos en línea.

+0

gracias amigo, def a up votar. ¿Puedes hacer un pequeño ejemplo o comprimir la razón en 50 palabras? –

+1

@ewernli: El enlace estaba roto, por favor, corrígelo. ¡Gracias! –

+1

@KugathasanAbimaran ¡El enlace funciona nuevamente! – ewernli

12

que tenía el mismo problema:

Seguridad - matriz se almacena directamente La matriz proporcionada por el usuario 'palomitas' se almacena directamente.

mi método original:

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

fijo se volvieron a:

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

Otro Ejemplo:

Seguridad - matriz se almacena directamente La matriz proporcionada por el usuario

private String[] arrString; 

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

fijo:

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

Para eliminarlos hay que clonar la matriz antes de guardar/devolverlo como se muestra en la siguiente implementación de la clase, por lo que nadie puede modificar u obtener los datos originales de su clase, pero solo una copia de ellos.

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

lo utilicé como esto y ahora no estoy recibiendo ninguna violación SONAR ...

0

Hay ciertos casos en los que es una decisión de diseño y no perdido. En estos casos, debe modificar las reglas de Sonar para excluirlo, de modo que no muestre dichos problemas en el informe.

2

Es más fácil que todo esto. Solo necesita cambiar el nombre del parámetro de método a cualquier otra cosa para evitar violaciones de 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); 
      } 

    } 
Cuestiones relacionadas