Open fdopen opened 4 years ago
There's something odd about this, since whichever struct layout the compiler uses, it's always valid to read from and write to struct fields through a pointer. It seems that the packed structs rather than the read/write code are the source of undefined behaviour.
I think it might be the casting to an unaligned pointer that is the undefined behaviour (the cast will always be aligned in the case of a normal, unpacked struct).
Found a good explanation here: https://stackoverflow.com/questions/46790550/c-undefined-behavior-strict-aliasing-rule-or-incorrect-alignment/46790815#46790815
it's always valid to read from and write to struct fields through a pointer.
No, just simple assignments are valid, when the type definition of the packed struct is present. Taking the address of a packed struct member is dodgy, because the address might not be a multiple of its type's alignment. Compilers warn about it, if the context is present:
typedef struct __attribute__((packed)) packed {
char c;
int x;
} packed;
void foo(void){
packed a = {'a',1};
int b = a.x; /* valid, because type definition of packed is known */
int * c = &a.x; /* invalid, warning enabled by default with recent
gcc and clang versions: -Waddress-of-packed-member: "taking address of
packed member of ‘struct packed’ may result in an unaligned pointer value"
*/
}
And the address of a packed struct members might be passed to ctypes_read
and ctypes_write
where the casts wrongly tell the compiler that the pointers are suitably aligned.
@fdopen: I mean that packed structs aren't part of standard C, and in standard C, a program that (1) takes the address of a struct field, then (2) reads/writes through that address during the object's lifetime is always valid.
I agree that reading/writing through an misaligned pointer is an error. But what's odd here is that the problem arises in step (1), and the proposed fix is to change step (2). One possible consequence of this approach is that every read and write to memory will suffer a performance cost for potentially misaligned access.
When stub generation is used, Ctypes can also deal with packed structs. Once packed structs are use, the pointer arithmetic inside
ctypes_read
andctypes_write
is not longer valid (similar issue like #584 ). The test doesn't produce any error - C compilers are quite tolerant. But libubsan would complain: