Jump to page: 1 2
Thread overview
Null pointer in __vptr
Nov 19, 2021
frame
Nov 19, 2021
Adam D Ruppe
Nov 19, 2021
frame
Nov 19, 2021
Adam D Ruppe
Nov 19, 2021
frame
Nov 22, 2021
bauss
Nov 22, 2021
frame
Nov 19, 2021
Ali Çehreli
Nov 20, 2021
frame
Nov 21, 2021
Ali Çehreli
Nov 21, 2021
frame
November 19, 2021

Got a suspicious interface instance in the debugger and question myself:

Is a null pointer entry in the __vptr[] valid or always a sign for corruption/wrong cast somewhere? thx

November 19, 2021
On Friday, 19 November 2021 at 15:37:59 UTC, frame wrote:
> Is a null pointer entry in the __vptr[] valid or always a sign for corruption/wrong cast somewhere? thx

The `destroy` function (as well as other class destruction) will null out the whole vtable to help make use-after-free an obvious error. Possible that happened to you.
November 19, 2021
On Friday, 19 November 2021 at 15:46:41 UTC, Adam D Ruppe wrote:

> The `destroy` function (as well as other class destruction) will null out the whole vtable to help make use-after-free an obvious error. Possible that happened to you.

So, a partial nulled table shouldn't exist, right? like this:

__vptr[0]: address
__vptr[1]: 0000000
__vptr[2]: address
__vptr[3]: address
__vptr[4]: address
__vptr[5]: address
...

Because 0 should point to the object instance and next offsets are pointers to the member functions, correct?
November 19, 2021
On Friday, 19 November 2021 at 18:04:17 UTC, frame wrote:
> So, a partial nulled table shouldn't exist, right? like this:

Indeed.

I've gotten that before as a result of a compiler bug... I had an abstract method that wasn't implemented but the compile time error got swallowed by a bug and thus the null method made its way to the binary.

I think that bug was fixed.... but still you might want to check your code for the `abstract` keyword and ensure they are legit implemented in your cases.

November 19, 2021
On Friday, 19 November 2021 at 18:14:03 UTC, Adam D Ruppe wrote:

> I've gotten that before as a result of a compiler bug... I had an abstract method that wasn't implemented but the compile time error got swallowed by a bug and thus the null method made its way to the binary.

You got it! It was an abstract class involved and the method signature was just wrong, but no compile error. Thanks!

November 19, 2021
On 11/19/21 10:04 AM, frame wrote:
> On Friday, 19 November 2021 at 15:46:41 UTC, Adam D Ruppe wrote:
>
>> The `destroy` function (as well as other class destruction) will null
>> out the whole vtable to help make use-after-free an obvious error.
>> Possible that happened to you.
>
> So, a partial nulled table shouldn't exist, right? like this:
>
> __vptr[0]: address
> __vptr[1]: 0000000
> __vptr[2]: address
> __vptr[3]: address
> __vptr[4]: address
> __vptr[5]: address
> ....
>
> Because 0 should point to the object instance

I am not sure that's correct. The way I picture it, the code reaches the __vptr by following a pointer; so it's already known. Additionally, I am under the impression that there is only one __vptr for a given type, which all class objects of that type point to.

> and next offsets are pointers to the member functions, correct?

My understanding is that all entries are that.

Ali

November 20, 2021
On Friday, 19 November 2021 at 21:09:16 UTC, Ali Çehreli wrote:

> I am not sure that's correct. The way I picture it, the code reaches the __vptr by following a pointer; so it's already known. Additionally, I am under the impression that there is only one __vptr for a given type, which all class objects of that type point to.

I think this is true for an object instance. But from an interface instance, the object instance must be accessible somewhere? This is also how I would read the doc:

> The vtbl[0] entry is a pointer to the corresponding instance of the object.Interface class.

On the other hand, I don't know what the debugger is really showing here - it's printed as void* array and I wonder where it gets the length of the array.
November 20, 2021
On 11/20/21 7:19 AM, frame wrote:

> I think this is true for an object instance. But from an interface
> instance, the object instance must be accessible somewhere?

Everything needed is available from the pointer to a class object (or interface). There are some offset arithmetic involved to get to the right vtbl pointer but the pointer of an object cannot be stored anywhere in the vtbl because there is just one vtbl but very many objects.

> This is also
> how I would read the doc:
>
>> The vtbl[0] entry is a pointer to the corresponding instance of the
>> object.Interface class.

That is from

  https://dlang.org/spec/abi.html

What they mean with object.Instance is the following definition I find e.g. in my /usr/include/dmd/druntime/import/object.d file:

/**
 * Information about an interface.
 * When an object is accessed via an interface, an Interface* appears as the
 * first entry in its vtbl.
 */
struct Interface
{
    TypeInfo_Class   classinfo;  /// .classinfo for this interface (not for containing class)
    void*[]     vtbl;
    size_t      offset;     /// offset to Interface 'this' from Object 'this'
}

So, the first entry is a pointer to that struct.

The ABI document mentions "pointer to instance of TypeInfo" as well, which is defined in the same object.d as well:

/**
 * Runtime type information about a type.
 * Can be retrieved for any type using a
 * $(GLINK2 expression,TypeidExpression, TypeidExpression).
 */
class TypeInfo
{
  // ...
}

Ali

November 21, 2021
On Sunday, 21 November 2021 at 02:43:12 UTC, Ali Çehreli wrote:

> There are some offset arithmetic involved to get to the right vtbl pointer but the pointer of an object cannot be stored anywhere in the vtbl because there is just one vtbl but very many objects.

Ok, so they mean by instance is only one instance by type but not data instance, got it.




November 22, 2021
On Friday, 19 November 2021 at 20:27:11 UTC, frame wrote:
> On Friday, 19 November 2021 at 18:14:03 UTC, Adam D Ruppe wrote:
>
>> I've gotten that before as a result of a compiler bug... I had an abstract method that wasn't implemented but the compile time error got swallowed by a bug and thus the null method made its way to the binary.
>
> You got it! It was an abstract class involved and the method signature was just wrong, but no compile error. Thanks!

Seems like it was only partially fixed then, specifically for missing abstract methods, but not whether the signature was correct or not.

Seems like a critical bug to me.
« First   ‹ Prev
1 2