NullReferenceException vs. invalid address

Hi,

The ECMA Standard states

"The results of all CIL instructions that return addresses (e.g., ldloca and ldarga) are safely aligned."

Now, let us assume that I have a local variable V whose declared type is a (managed) pointer type. Moreover, let us assume that V has not been initialized. In other words, that would mean that V carries an arbitrary address. Depending on the target architecture, this address might be unaligned, i.e., invalid!

If I now use the instruction "ldloc V" to load V's value, I will practically push onto the stack that arbitrary address carried by V, right That arbitrary address is regarded as V's value.

An attempt to use that address with "ldind" or "stind" can throw a NullReferenceException (depending on the target architecture)!

In principle:
  • as long as there is no read/overwrite of the value carried by the invalid address, no NullReferenceException is raised;
  • if a read/overwrite occurs (by means of ldind or stind), then NullReferenceException is thrown. Note that there is no other way except ldind and stind to read/overwrite that value!
So, an unitialized local variable whose declared type is a pointer type might carry an invalid address.

Is there another VERIFIABLE way to produce invalid addresses

Many thanks for any suggestion,
Cat
a


Answer this question

NullReferenceException vs. invalid address

  • MTV

    catalinione wrote:
    Hi,

    The ECMA Standard states

    "The results of all CIL instructions that return addresses (e.g., ldloca and ldarga) are safely aligned."

    Now, let us assume that I have a local variable V whose declared type is a (managed) pointer type. Moreover, let us assume that V has not been initialized. In other words, that would mean that V carries an arbitrary address. Depending on the target architecture, this address might be unaligned, i.e., invalid!

    If I now use the instruction "ldloc V" to load V's value, I will practically push onto the stack that arbitrary address carried by V, right That arbitrary address is regarded as V's value.

    An attempt to use that address with "ldind" or "stind" can throw a NullReferenceException (depending on the target architecture)!

    In principle:
    • as long as there is no read/overwrite of the value carried by the invalid address, no NullReferenceException is raised;
    • if a read/overwrite occurs (by means of ldind or stind), then NullReferenceException is thrown. Note that there is no other way except ldind and stind to read/overwrite that value!

    So, an unitialized local variable whose declared type is a pointer type might carry an invalid address.

    Is there another VERIFIABLE way to produce invalid addresses

    Many thanks for any suggestion,
    Cat
    a

    A reference (there are no "pointers") variable that you don't assign to will be initialized with null. There are no such things as arbitrary addresses in a managed framework.

    There is no built-in way to produce an invalid address with managed types.



  • GLutz78

    I think one of the main question here is:

    do the managed pointer types, e.g., int32&, valuetype P &, have a default value If yes, what is the value Is it "null"

    If yes, why the ldflda instruction in my example above does NOT raise a NullReferenceException according to the standard spec for ldflda

    Cata



  • Burnt1ce

    I'm not clear one what you're trying to accomplish. the docs for the .locals directive says reference variables are initialized to null and value variables intialized to zero. Regardless of how you view what a managed pointer is, it should still still start out being equivalent to null--which is what you're observing. You can't assign an arbitrary address to anything managed; that's the point of being managed.

  • Robert3234

    All value types are intialized to zero. This, of course, is equivalent to null.

  • Adam Anderly

    The reference is: page 75 in Partition III, section 3.42

    I thought that the pointers are reference types (see page 18 in Partition I, section 8.2.1). And yet, you cannot assign "null" to a pointer type.

    And something more:

    Assume that I have a value class P with an instance int32 field F. Moreover, my local variable is of declared type valuetype P & (so again a pointer type).

    If I access the address of field P::F, I get no NullReferenceException! That is,

    ldloc V_0
    ldflda int32 P::F

    runs with no exception!

    But, if instead of the address I want the value of P::F, then I get a NullReferenceException!

    ldloc V_0
    ldfld int32 P::F

    throws a NullReferenceException!

    All my examples are verifiable! and this is OK.

    Cata

  • Shajeel

    Peter, so far I was thinking that it's null. But now ... I'm not sure anymore.

    If it's null, why I don't get a NullReferenceException with the ldflda instruction according to the spec:

    "System.NullReferenceException is thrown if obj (in our case, the address on the stack) is null and the field isn’t static."

    Even if you pass that address (invalid in my conception) as the this argument to an instance method, you get no
    System.NullReferenceException (although the spec says you should get)!

    Cata

  • dhanezep

    I can't find the specific reference, but managed pointers are value types; and therefore are initialized to zero.

    But, ECMA 335 does mention managed pointers cannot have a value of null (in informative text, so it shouldn't be considered part of the standard).



  • Scott E Johnson

    Sorry, I don't get your answer.

    The declared of the variable is a pointer type int32& and not the value type int32. It has nothing to do with the default value of int32!

    About the ldind instruction, the ECMA Standard for CLR says:

    "The address specified by addr (the address on the stack) shall be to a location with the natural alignment of <type> or a NullReferenceException might occur"

    "System.NullReferenceException can be thrown if an invalid address is detected."

    So, my example contains an invalid address (wrt my architecture), right

    Cata

  • Leandro Loureiro dos Santos

    Peter, thanks for the answer.

    Take the following example. A method with one local variable of declared type int32&.

    .locals init (int32& V_0)

    ldloc.s V_0
    ldind.i4

    The ldind.i4 instruction throws a NullReferenceException (on my machine). Why

    My answer is: because upon the method's entry, the variable V_0 has not been automatically initialized as it happens with local variables of non-pointer types! So, the value of V_0, loaded onto the stack by ldloc.s V_0, is an invalid address.

    Cata

  • NullReferenceException vs. invalid address