CIL 和数组边界检查

发布于 2024-12-28 19:55:43 字数 1093 浏览 2 评论 0 原文

让我们假设以下 CIL 程序:

.assembly extern mscorlib {}
.assembly Program {}

.method private static void Main() cil managed
{
    .entrypoint
    .maxstack 4

    .locals init ( int32[] a,
               uint32   t )

    // Creates an array of int of size 10
    ldc.i4 10
    newarr int32
    stloc.0

    // Writes 0xaabbccdd at the index 2 of the array
    ldloc.0
    ldc.i4.2
    ldc.i4 0xaabbccdd
    stelem.i4

    // Loads
    ldloc.0
    ldc.i4 9 // <HERE>
    ldelem.i1

    stloc.1
    ldstr "Value: 0x{0:x8}"
    ldloc.1
    box [mscorlib]System.UInt32
    call void [mscorlib]System.Console::WriteLine(string, object)

    ret
}

该程序:

  • 创建一个 int 大小为 10 的数组
  • 在数组的索引 2 处写入 0xaabbccdd
  • 尝试使用 ldelem.i1 读取数组中的一个字节
  • 打印结果

诀窍是我使用“ldelem.i1”。 i1”而不是更标准的“idelem.i4”以解决性能问题(我想避免进行屏蔽),其想法是像 C 中的指针一样访问数组的数据。

但是事情不太好,因为当 ldelem.i1 的参数索引超过 10 时,程序会崩溃 (IndexOutOfRangeException)。 这使得这个技巧毫无用处,因为我无法访问第三个索引处的整数前半部分之后的数据。

理想情况下,我想访问索引 39 之前的字节,它对应于索引 9 处整数的最后一个字节。

如果有人对这一点有一些想法,我将非常感激。

Let us assume the following CIL program:

.assembly extern mscorlib {}
.assembly Program {}

.method private static void Main() cil managed
{
    .entrypoint
    .maxstack 4

    .locals init ( int32[] a,
               uint32   t )

    // Creates an array of int of size 10
    ldc.i4 10
    newarr int32
    stloc.0

    // Writes 0xaabbccdd at the index 2 of the array
    ldloc.0
    ldc.i4.2
    ldc.i4 0xaabbccdd
    stelem.i4

    // Loads
    ldloc.0
    ldc.i4 9 // <HERE>
    ldelem.i1

    stloc.1
    ldstr "Value: 0x{0:x8}"
    ldloc.1
    box [mscorlib]System.UInt32
    call void [mscorlib]System.Console::WriteLine(string, object)

    ret
}

This program:

  • creates an array of int size 10
  • writes 0xaabbccdd at index 2 of the array
  • tries to read one byte in the array using ldelem.i1
  • prints the result

The trick is that I use "ldelem.i1" instead of the more standard "idelem.i4" for performance issues (I want to avoid doing masking) The idea is to access to the data of the array the way one does with pointers in C.

But things are not so nice because the program crashes (IndexOutOfRangeException) for indexes of more than 10 as argument for ldelem.i1.
This males the trick useless as I can't access data after the first half of the integer at the third index.

Ideally, I want to access bytes up to index 39, which corresponds to the last byte of the integer at index 9.

I would very much appreciate if somebody had some ideas on this point.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

森林散布 2025-01-04 19:55:43

有趣的。 ECMA-335 规定,如果索引大于或等于数组的大小(这肯定是),它将引发异常。让我惊讶的不是抛出异常,而是索引首先被视为 int 数组中的 byte 索引 - 我可以'没有看到任何地方都指定了这一点。

怀疑您进入了未指定行为的领域,很可能是不打算指定的行为 - 我怀疑您只是不打算使用int 数组上的 >ldelem.i1。

Interesting. The ECMA-335 states that it will throw an exception if the index is greater than or equal to the size of the array, which it definitely is. What surprises me about this isn't that the exception is thrown, but that the index is treated as a byte index into an int array in the first place - I can't see that that's specified anywhere.

I suspect you're into the realms of unspecified behaviour, quite possibly behaviour which isn't intended to be specified - I suspect you're just not meant to use ldelem.i1 on an int array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文