Sdílet prostřednictvím


CA2105: Pole polí by neměly být pouze pro čtení

TypeName

ArrayFieldsShouldNotBeReadOnly

CheckId

CA2105

Kategorie

Microsoft.Security

Narušující změna

Narušující

Příčina

Veřejné nebo chráněné pole obsahující pole je určeno pouze pro čtení.

Popis pravidla

Při aplikování readonly (ReadOnly v rámci modifikátoru Visual Basic) na jiné obsahující pole. Pole nemůže být změněno k odkazování na jiné pole.Avšak prvky pole, které jsou uloženy v poli určeném pouze pro čtení mohou být změněny.Kód, který provádí rozhodnutí nebo provádí operace, které jsou založeny na prvcích pole určeného jen pro čtení, které je veřejně přístupné mohou vést k zneužitelné chybě zabezpečení.

Je třeba brát v potaz, že veřejné pole také porušuje pravidlo návrhu CA1051: Nedeklarujte viditelná pole instance.

Jak vyřešit porušení

Pro vyřešení slabého místa v zabezpečení, které je identifikováno tímto pravidlem nelze spoléhat na obsahy pole určeného pouze pro čtení, ke kterému lze veřejně přistupovat.Je důrazně doporučeno použít jeden z následujících postupů:

  • Pole nahraďte kolekcí se silnými typy, které nelze změnit.Další informace naleznete v tématu ReadOnlyCollectionBase.

  • Nahraďte veřejné pole metodou, která vrací klon soukromého pole.Protože kód není závislý na klonu, nehrozí nebezpečí při úpravě jeho prvků.

Pokud zvolíte druhý přístup, nenahrazujte pole vlastností; vlastnosti, které vrací pole nepříznivě ovlivňují výkon.Další informace naleznete v tématu CA1819: Vlastnosti by neměly vracet pole.

Kdy potlačit upozornění

Vyloučení upozornění tohoto pravidla se důrazně nedoporučuje.V místě, kde obsah pole určeného jen pro čtení není důležitý, nedochází k téměř žádným případům.Pokud se vás tento případ týká, je zapotřebí odstranit modifikátor readonly, místo odebrání této zprávy.

Příklad

Tento příklad ukazuje nebezpečí porušení tohoto pravidla.V první části je zobrazen příklad knihovny typu, MyClassWithReadOnlyArrayField, který obsahuje dvě pole (grades a privateGrades), která nejsou zabezpečená.Pole grades je veřejné a proto není odolné vůči libovolnému volajícímu.Pole privateGrades je soukromé, ale stále není odolné, protože je vráceno volajícím v rámci metody GetPrivateGrades.Pole securePrivateGrades je vystaveno bezpečným způsobem pomocí metody GetSecurePrivateGrades.Je deklarováno jako soukromé tak, aby dodržovalo postupy dobrého návrhu.Druhá část zobrazuje kód, který mění hodnoty uložené ve členech grades a privateGrades.

V následujícím příkladu je zobrazen příklad knihovny tříd.

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

Následující kód používá knihovnu tříd příklad pro zobrazení problémů zabezpečení pole určeného jen pro čtení.

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

Výstup z tohoto příkladu je následující:

  

Viz také

Referenční dokumentace

Array

ReadOnlyCollectionBase