CA2105: I campi di matrici non devono essere di sola lettura
TypeName |
ArrayFieldsShouldNotBeReadOnly |
CheckId |
CA2105 |
Category |
Microsoft.Security |
Breaking Change |
Breaking |
Causa
Un campo pubblico o protetto che contiene una matrice è dichiarato in sola lettura.
Descrizione della regola
Quando si applica il modificatore readonly (ReadOnly in Visual Basic) a un campo contenente una matrice, il campo non può essere modificato affinché faccia riferimento a un'altra matrice.È tuttavia possibile modificare gli elementi della matrice archiviati in un campo in sola lettura.Il codice con il quale si effettuano scelte o si eseguono operazioni in base agli elementi di una matrice in sola lettura accessibile pubblicamente potrebbe essere vulnerabile dal punto di vista della sicurezza.
Si noti che la presenza di un campo pubblico viola anche la regola di progettazione CA1051: Non dichiarare campi di istanza visibili.
Come correggere le violazioni
Per correggere la vulnerabilità di sicurezza identificata da questa regola, non basarsi sul contenuto di una matrice in sola lettura accessibile pubblicamente.È consigliabile eseguire una delle procedure riportate di seguito:
Sostituire la matrice con una raccolta fortemente tipizzata non modificabile.Per ulteriori informazioni, vedere ReadOnlyCollectionBase.
Sostituire il campo pubblico con un metodo che restituisca un duplicato di una matrice privata.Poiché il codice non si basa sul duplicato, non vi è pericolo nel caso gli elementi vengano modificati.
Se si sceglie il secondo approccio, non sostituire il campo con una proprietà; le proprietà che restituiscono matrici influiscono negativamente sulle prestazioni.Per ulteriori informazioni, vedere CA1819: Le proprietà non devono restituire matrici.
Esclusione di avvisi
L'esclusione di un avviso da questa regola è vivamente sconsigliata.Praticamente non esistono scenari in cui il contenuto di un campo in sola lettura non sia importante.Se questo fosse il caso, rimuovere il modificatore readonly anziché escludere il messaggio.
Esempio
In questo esempio vengono illustrati i rischi derivanti dalla violazione di questa regola.Nella prima parte è illustrata una libreria di esempio che dispone di un tipo, MyClassWithReadOnlyArrayField, contenente due campi (grades e privateGrades) non sicuri.Il campo grades è pubblico e pertanto vulnerabile a qualsiasi chiamante.Il campo privateGrades è privato, ma comunque vulnerabile poiché viene restituito ai chiamanti dal metodo GetPrivateGrades.Il campo securePrivateGrades è esposto in modo sicuro dal metodo GetSecurePrivateGrades.È dichiarato come privato, in conformità alle migliori pratiche di progettazione.Nella seconda parte è illustrato del codice che modifica i valori archiviati nei membri grades e privateGrades.
Nell'esempio che segue è riportata la libreria di classi di esempio.
using System;
namespace SecurityRulesLibrary
{
public class MyClassWithReadOnlyArrayField
{
public readonly int[] grades = {90, 90, 90};
private readonly int[] privateGrades = {90, 90, 90};
private readonly int[] securePrivateGrades = {90, 90, 90};
// Making the array private does not protect it because it is passed to others.
public int[] GetPrivateGrades()
{
return privateGrades;
}
//This method secures the array by cloning it.
public int[] GetSecurePrivateGrades()
{
return (int[])securePrivateGrades.Clone();
}
public override string ToString()
{
return String.Format("Grades: {0}, {1}, {2} Private Grades: {3}, {4}, {5} Secure Grades, {6}, {7}, {8}",
grades[0], grades[1], grades[2], privateGrades[0], privateGrades[1], privateGrades[2], securePrivateGrades[0], securePrivateGrades[1], securePrivateGrades[2]);
}
}
}
Nel codice riportato di seguito viene utilizzata la libreria di classi di esempio per illustrare problemi di sicurezza di matrici in sola lettura.
using System;
using SecurityRulesLibrary;
namespace TestSecRulesLibrary
{
public class TestArrayReadOnlyRule
{
[STAThread]
public static void Main()
{
MyClassWithReadOnlyArrayField dataHolder =
new MyClassWithReadOnlyArrayField();
// Get references to the library's readonly arrays.
int[] theGrades = dataHolder.grades;
int[] thePrivateGrades = dataHolder.GetPrivateGrades();
int[] theSecureGrades = dataHolder.GetSecurePrivateGrades();
Console.WriteLine(
"Before tampering: {0}", dataHolder.ToString());
// Overwrite the contents of the "readonly" array.
theGrades[1]= 555;
thePrivateGrades[1]= 555;
theSecureGrades[1]= 555;
Console.WriteLine(
"After tampering: {0}",dataHolder.ToString());
}
}
}
Di seguito è riportato l'output dell'esempio: