use memcpy inside ctypes_read/ctypes_write to avoid undefined behaviour#645
use memcpy inside ctypes_read/ctypes_write to avoid undefined behaviour#645fdopen wants to merge 2 commits intoyallop:masterfrom
Conversation
Stub generations also supports packed structs. The addresses are therefore not guaranteed to be properly aligned.
|
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: |
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 |
|
@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_readandctypes_writeis not longer valid (similar issue like #584 ).The test doesn't produce any error - C compilers are quite tolerant. But libubsan would complain: