2011-06-24 21 views
8

Poznaję kod zarządzany i niezarządzany w środowisku CLR. Więc napisałem ten przykład ze wskaźnikami w stylu C w C#:Co jest niebezpieczne w tym kodzie?

unsafe static void Main(string[] args) 
{ 
    int x; 
    int* y; 
    y = &x; 
    *y = 50; 
    Console.WriteLine(*y); 
    Console.WriteLine(((int)y).ToString()); 
} 

Więc zastanawiam się, co naprawdę jest niebezpieczne w kodzie IL, że mam z powyższym kodzie?

.assembly extern mscorlib 
{} 
.assembly UnsafePointers 
{} 
.module UnsafePointers.exe 
.class private auto ansi beforefieldinit UnsafePointers.Program 
extends [mscorlib]System.Object 
{ 
    .method private hidebysig static void Main(string[] args) cil managed 
    { 
     .entrypoint 
     // Code size  34 (0x22) 
     .locals init (int32 x, 
     int32* y) 
     IL_0001: ldloca  x 
     IL_0003: conv.u 
     IL_0004: stloc  y 
     IL_0005: ldloc y 
     IL_0006: ldc.i4 50 
     IL_0008: stind.i4 
     IL_0009: ldloc  y 
     IL_000a: ldind.i4 
     IL_000b: call  void [mscorlib]System.Console::WriteLine(int32) 
     IL_0010: nop 
     IL_0011: ldloca  y 
     IL_0012: conv.i4 
     IL_0016: call  instance string [mscorlib]System.Int32::ToString() 
     IL_001b: call  void [mscorlib]System.Console::WriteLine(string) 
     IL_0021: ret 
    } 
}  

Czy CLR zarządza tym kodem? A co może pójść nie tak z powyższym kodem?

+0

Oprócz tego, co już powiedzieli inni, jest to nadal w 100% zarządzany kod. Po prostu nie jest to weryfikowalne pod względem pamięci, ponieważ narzędzie peverify może ci powiedzieć. – John

Odpowiedz

6

To, co czyni ten kod niebezpiecznym, to użycie instrukcji "ldind.i4". To ładuje podpisaną 4-bajtową liczbę całkowitą z adresu pamięci. Można podać dowolny adres pamięci, umożliwiając odczyt z dowolnego adresu pamięci w bieżącym procesie. Jest to uważane za niebezpieczne i niemożliwe do zweryfikowania. Na przykład możesz użyć tego do przejrzenia innych domen aplikacji, co jest niedozwolone.

+0

Dziękuję za odpowiedź! Myślę, że to wyjaśnienie było tym, czego szukałem. Teraz wydaje mi się to tak oczywiste, ale do tej pory go nie widziałem. – vldmrrdjcc

+1

Peverify kończy się niepowodzeniem na 'conv.u', co oznacza, że ​​odmawia on nazwania go bezpiecznym do ponownego wczytywania załadowanego adresu jako liczby całkowitej. – John

6

To się nazywa niebezpieczne, częściowo dlatego, że nie jest zarządzane.

Można łatwo tworzyć C++ wycieków pamięci styl, nie istnieją żadne kontrole graniczne oraz inne problemy ...

Miły artykuł o kodzie niebezpieczny, również można znaleźć kilka zagrożeń:

Using Unsafe Code in C#

+0

To nadal kod zarządzany, po prostu nie można go zweryfikować. – John

3

Ogólnie rzecz biorąc, słowo kluczowe unsafe umożliwia bezpośredni dostęp do pamięci i dlatego omija wszystkie kontrole weryfikacyjne i bezpieczeństwa przeprowadzane przez CLR.

Oto dobry artykuł na temat wykorzystania i wpływu kodu unsafe: http://blogs.msdn.com/b/sebby1234/archive/2006/04/05/565090.aspx

+0

To bardzo fajny artykuł, myślę, że tego właśnie szukałem. Dzięki! Jeszcze jedno pytanie: jak CLR wie, że jakiś kod IL w niebezpieczny sposób?Czy przegląda zadeklarowane typy i czy widzi na przykład typ wskaźnika, który decyduje, że kod jest niebezpieczny? – vldmrrdjcc

4

niebezpieczne nie mogą oznaczać niebezpieczne, ale jest jedna rzecz, która jest ważna w niebezpieczny kod: jest nieweryfikowalne. Może to oznaczać kilka rzeczy, na przykład nie sprawdzanie granic tablicy. W twoim prostym przykładzie. nie ma w tym nic groźnego ani przerażającego. To całkiem proste.

Może to być niebezpieczne, ponieważ powoduje również obejście większości mechanizmów zabezpieczeń w .NET Framework; dlatego tak bezpieczny kod wymaga pełnego zaufania.

Niebezpieczna! = Niezarządzana. Niebezpieczny oznacza, że ​​może manipulować wskaźnikami.

0

Domyślnie kompilatory C# i Visual Basic.NET firmy Microsoft generują "bezpieczny" kod. Bezpieczny kod to kod, który jest weryfikowalny. Jednak używając niebezpiecznego słowa kluczowego w języku C# lub używając innych języków (takich jak C++ z Managed Extensions lub IL Assembly Language), możesz stworzyć kod, który nie może być weryfikowalny. Oznacza to, że kod może być bezpieczny, ale weryfikacja nie jest w stanie tego udowodnić.

administrator może wyłączyć weryfikację (za pomocą przystawki konsoli zarządzania ".NET Management" Microsoft konsoli zarządzania). Po wyłączeniu weryfikacji kompilator JIT skompiluje niepotwierdzoną wartość IL do instrukcji natywnego procesora; jednak administrator bierze pełną odpowiedzialność za zachowanie kodu.

Powiązane problemy