Preferences

Canonical example:

    union {
        char* p;
        long i;
    };
Then say that the attacker can write arbitrary integers into `i` and then trigger dereferences on `p`.

The standard does not assign meaning to this sequence of execution, so an implementation can detect this and abort. This is not just hypothetical: existing implementations with pointer capabilities (Fil-C, CHERI targets, possibly even compilers for IBM i) already do this. Of course, such C implementations are not widely used.

The union example is not particularly problematic in this regard. Much more challenging is pointer arithmetic through uintptr_t because it's quite common. It's probably still solvable, but at a certain point, changes the sources becomes easier, even at at scale (say if something uses the %p format specifier with sprintf/sscanf).

> The standard does not assign meaning to this sequence of execution, so an implementation can detect this and abort.

Real C programs use these kinds of unions and real C compilers ascribe bitcast semantics to this union. LLVM has a lot of heavy machinery to make sure that the programmer gets exactly what then expected here.

The spec is brain damage. You should ignore it if you want to be able to reason about C.

> This is not just hypothetical: existing implementations with pointer capabilities (Fil-C, CHERI targets, possibly even compilers for IBM i) already do this

Fil-C does not abort when you use this union. You get memory safe semantics:

- you can use `i` to change the pointer’s intval. But the capability can’t be changed that way. So if you make a mistake you’ll end up with an OOB pointer.

- you can use `i` to read the pointer’s current intval just as if you had done an ptrtoint cast.

I think CHERI also does not abort on the union itself. I think storing to `i` removes the capability bit so `p` crashes on deref.

> The union example is not particularly problematic in this regard. Much more challenging is pointer arithmetic through uintptr_t because it's quite common.

The union problem is one of the reasons why C is not memory safe, because C compilers give unions the expected structured assembly semantics, not whatever nonsense is in the spec.

This item has no comments currently.

Keyboard Shortcuts

Story Lists

j
Next story
k
Previous story
Shift+j
Last story
Shift+k
First story
o Enter
Go to story URL
c
Go to comments
u
Go to author

Navigation

Shift+t
Go to top stories
Shift+n
Go to new stories
Shift+b
Go to best stories
Shift+a
Go to Ask HN
Shift+s
Go to Show HN

Miscellaneous

?
Show this modal