Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing a struct member from what is not the same struct type

The code below looks crazy, because I am interested in finding out the limits of what’s possible, and it isn’t exactly what I’m doing in my real code. It compiles without warnings and works as expected, printing “onref: 42”, but what I’m wondering is if it’s guaranteed to work or if the line marked “the interesting line” is actually undefined behavior.

The top candidate for something constituting a problem here is that h is set to point outside of defined variables, so accessing h->other or h->map could in principle result in segmentation violation, but making sure that those are not accessed, by first checking the value of onref to determine if the struct is a valid H, should make it good, shouldn’t it?

#include <stdio.h>
#include <inttypes.h>

struct H {
    struct H *other;
    uint32_t *map;
    uint64_t onref;
};

struct G {
    uint64_t onref;
    char data[10];
};

#define ONREF_VALUE_THAT_SHOWS_ITS_NOT_AN_H 42

void foo(void *p) {
    struct H *h = (struct H *) p - 1;           // the interesting line
    printf("onref: %"PRIu64"\n", h->onref);
}

int main() {
    static struct G g;

    g.onref = ONREF_VALUE_THAT_SHOWS_ITS_NOT_AN_H;
    foo(&g.data);
}
like image 859
njlarsson Avatar asked Dec 21 '25 22:12

njlarsson


1 Answers

The pointer arithmetic is undefined behaviour in

struct H *h = (struct H *) p - 1;

even before you attempt to dereference it. C23 says

6.5.6 Additive operators

9 ... If the pointer operand and the result do not point to elements of the same array object or one past the last element of the array object, the behavior is undefined.

In your 'interesting' line p was pointing to the first element of an array.

like image 79
Weather Vane Avatar answered Dec 24 '25 17:12

Weather Vane



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!