CA2105: Los campos de matrices no deben ser de solo lectura

Elemento Valor
RuleId CA2105
Category Microsoft.Security
Cambio importante Problemático

Causa

Un campo público o protegido que contiene una matriz se declara como de solo lectura.

Nota

Esta regla está en desuso. Para más información, consulte Reglas en desuso.

Descripción de la regla

Cuando se aplica el modificador readonly (ReadOnly en Visual Basic) a un campo que contiene una matriz, el campo no se puede cambiar para hacer referencia a una matriz distinta. Sin embargo, se pueden cambiar los elementos de la matriz almacenados en un campo de solo lectura. El código que toma decisiones o realiza operaciones basadas en los elementos de una matriz de solo lectura a la que se puede acceder públicamente podría contener una vulnerabilidad de seguridad aprovechable.

Tenga en cuenta que tener un campo público también infringe la regla de diseño CA1051: No declarar campos de instancia visibles.

Cómo corregir infracciones

Para reparar la vulnerabilidad de seguridad identificada por esta regla, no confíe en el contenido de una matriz de solo lectura a la que se pueda acceder públicamente. Se recomienda encarecidamente usar uno de los procedimientos siguientes:

  • Reemplace la matriz por una colección fuertemente tipada que no se pueda cambiar. Para obtener más información, vea System.Collections.ReadOnlyCollectionBase.

  • Reemplace el campo público por un método que devuelva un clon de una matriz privada. Como el código no se basa en el clon, no hay ningún peligro en modificar los elementos.

Si eligió el segundo enfoque, no reemplace el campo por una propiedad; las propiedades que devuelven matrices afectan negativamente al rendimiento. Para más información, consulte CA1819: Las propiedades no deben devolver matrices.

Cuándo suprimir las advertencias

No se recomienda encarecidamente excluir una advertencia de esta regla. Casi no se producen escenarios en los que el contenido de un campo de solo lectura no sea importante. Si este es el caso de su escenario, quite el modificador readonly en lugar de excluir el mensaje.

Ejemplo 1

En este ejemplo se muestran los peligros de infringir esta regla. La primera parte muestra una biblioteca de ejemplo que tiene un tipo, MyClassWithReadOnlyArrayField, que contiene dos campos (grades y privateGrades) que no son seguros. El campo grades es público y, por consiguiente, es vulnerable a cualquier autor de llamada. El campo privateGrades es privado, pero también es vulnerable porque el método GetPrivateGrades lo devuelve a los autores de llamadas. El método GetSecurePrivateGrades expone el campo securePrivateGrades de forma segura. Se declara como privado para seguir los procedimientos de diseño recomendados. En la segunda parte se muestra el código que cambia los valores almacenados en los miembros grades y privateGrades.

La biblioteca de clases de ejemplo aparece en el ejemplo siguiente.

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

Ejemplo 2

En el código siguiente se usa la biblioteca de clases de ejemplo para ilustrar los problemas de seguridad de las matrices de solo lectura.

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

La salida de este ejemplo es:

Before tampering: Grades: 90, 90, 90 Private Grades: 90, 90, 90  Secure Grades, 90, 90, 90
After tampering: Grades: 90, 555, 90 Private Grades: 90, 555, 90  Secure Grades, 90, 90, 90

Consulte también