Поделиться через


Поля массивов не должны быть доступны только для чтения

Обновлен: Ноябрь 2007

TypeName

ArrayFieldsShouldNotBeReadOnly

CheckId

CA2105

Категория

Microsoft.Security

Критическое изменение

Критическое

Причина

Открытое или защищенное поле, в котором содержится массив, объявлено как доступное только для чтения.

Описание правила

При применении модификатора readonly (ReadOnly в Visual Basic) к полю, содержащему массив, это поле нельзя изменить для связи с другим массивом. Однако элементы массива, хранящегося в доступном только для чтения поле, можно будет изменить. Код, используемый для принятия решений или выполнения действий на основе элементов общедоступного массива только для чтения, может содержать уязвимые места.

Следует обратить внимание, что наличие открытых полей также приводит к нарушению правила разработки Не объявляйте видимые поля экземпляров.

Устранение нарушений

Чтобы устранить нарушения системы безопасности, выявленные данным правилом, не следует использовать содержимое общедоступного массива только для чтения. Настоятельно рекомендуется воспользоваться одной из следующих процедур.

  • Замените массив строго типизированной неизменяемой коллекцией. Дополнительные сведения см. в разделе System.Collections.ReadOnlyCollectionBase.

  • Замените открытое поле методом, возвращающим копию закрытого массива. Поскольку код не использует копию, изменение элементов не будет представлять никакой опасности.

При выборе второго подхода не нужно заменять поле свойством; свойства, возвращающие массивы, оказывают негативное влияние на производительность. Дополнительные сведения см. в разделе Свойства не должны возвращать массивы.

Отключение предупреждений

Отключать вывод предупреждения для данного правила крайне нежелательно. Случаев, в которых содержимое поля, доступного только для чтения, является маловажным, практически не существует. Если это так в текущей ситуации, вместо отключения сообщения удалите модификатор readonly.

Пример

В следующем примере показана опасность нарушения данного правила. В первой части представлена библиотека с типом MyClassWithReadOnlyArrayField, где содержатся два поля (grades и privateGrades), безопасность которых не гарантируется. Поле grades является открытым и, следовательно, уязвимым к вызывающим методам. Поле privateGrades является закрытым, но все еще уязвимым, поскольку оно возвращается вызывающим методам с помощью метода GetPrivateGrades. Поле securePrivateGrades доступно в безопасном режиме за счет методаGetSecurePrivateGrades. Для соответствия рекомендациям разработки оно объявляется закрытым. Во второй части представлен код, изменяющий значения, которые хранятся в членах grades и privateGrades.

Образец библиотеки классов показан в следующем примере.

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

В следующем коде образец библиотеки классов используется для демонстрации проблем с безопасностью в массиве, доступном только для чтения.

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

Результатом выполнения примера являются следующие данные.

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

См. также

Ссылки

System.Array

System.Collections.ReadOnlyCollectionBase