这段代码有什么不安全的地方?
我正在学习 CLR 中的托管和非托管代码。 所以我用 C# 中的 C 风格指针编写了这个示例:
unsafe static void Main(string[] args)
{
int x;
int* y;
y = &x;
*y = 50;
Console.WriteLine(*y);
Console.WriteLine(((int)y).ToString());
}
所以我想知道从上面的代码中获得的 IL 代码中到底有什么不安全的地方?
.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
}
}
CLR 管理这段代码吗?上面的代码会出现什么问题?
I am learning about managed and unmanaged code in CLR.
So I wrote this example with C-style pointers in C#:
unsafe static void Main(string[] args)
{
int x;
int* y;
y = &x;
*y = 50;
Console.WriteLine(*y);
Console.WriteLine(((int)y).ToString());
}
So I am wondering what really is unsafe in IL code that I got from the code above?
.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
}
}
Does CLR manages this code? And what can go wrong with a code above?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使该代码不安全的是使用“ldind.i4”语句。这会从内存地址加载一个带符号的 4 字节整数。可以给出任何内存地址,允许您从当前进程中的任何内存地址读取。这被认为是不安全且无法验证的。例如,您可以使用它来查看其他应用程序域的内部,这是不允许的。
What makes this code unsafe is the use of the 'ldind.i4' statement. This loads a signed 4-byte integer from a memory address. Any memory address can be given, allowing you to read from any memory address in the current process. This is considered unsafe and unverifiable. For instance, you could use this to look inside other appdomains, which is not allowed.
它被称为不安全,部分原因是它不受管理。
您可以轻松地创建 C++ 风格的内存泄漏、没有边界检查以及其他问题...
一篇关于不安全代码的好文章,还列出了一些风险:
在 C# 中使用不安全代码
It's called unsafe, partly because it is not managed.
You can easily create c++ style memory leaks, there are no boundary checks, and other problems...
A nice article about unsafe code, also lists a few risks:
Using Unsafe Code in C#
不安全可能并不意味着危险,但在不安全代码中有一件事很重要:它无法验证。这可能意味着多种情况,例如不检查数组的边界。在你的简单例子中。并没有那么危险或可怕。这非常简单。
In 可能不安全,因为它还绕过了 .NET Framework 中的大多数安全机制;这就是为什么不安全的代码无论如何都需要完全信任。
不安全!=不受管理。不安全只是意味着它可以操作指针。
Unsafe may not mean dangerous, but there is one thing that is important in unsafe code: it is unverifiable. This can mean several things, such as not checking the bounds of an array. In your simple example. there isn't that much dangerous or scary about it. It's pretty straight forward.
In can be unsafe because it also gets around most of the security mechanisms in the .NET Framework; which is why unsafe code requires Full Trust anyway.
Unsafe != Unmanaged. Unsafe just means it can manipulate pointers.
一般来说,
unsafe
关键字允许您直接访问内存,因此绕过 CLR 的所有验证和安全检查。这是一篇关于
不安全
代码的使用和影响的好文章:http://blogs.msdn.com/b/sebby1234 /archive/2006/04/05/565090.aspx
In general, the
unsafe
keyword allows you direct access to memory and therefore bypasses all verification and safety checks by the CLR.Here's a good article on the use and impact of
unsafe
code:http://blogs.msdn.com/b/sebby1234/archive/2006/04/05/565090.aspx
默认情况下,Microsoft 的 C# 和 Visual Basic.NET 编译器生成“安全”代码。安全代码是可验证安全的代码。但是,使用 C# 的 unsafe 关键字或使用其他语言(例如带有托管扩展的 C++ 或 IL 汇编语言),您可能会生成无法验证安全的代码。也就是说,代码实际上可能是安全的,但验证无法证明这一点。
管理员可以选择关闭验证(使用“.NET Management”Microsoft
管理控制台管理单元)。关闭验证后,JIT 编译器会将无法验证的 IL 编译为本机 CPU 指令;但是,管理员对代码的行为负全部责任。
By default, Microsoft’s C# and Visual Basic.NET compilers produce “safe” code. Safe code is code that is verifiably safe. However, using C#’s unsafe keyword or using other languages (such as C++ with Managed Extensions or IL Assembly language), you can produce code that cannot be verifiably safe. That is, the code might, in fact, be safe, but the verification is unable to prove it.
an administrator can elect to turn verification off (using the ".NET Management" Microsoft
Management Console Snap-In). With verification off, the JIT compiler will compile unverifiable IL into native CPU instructions; however, the administrator is taking full responsibility for the code's behavior.