Is the load inconsistent due to cast behavior undefined?

Is there an inconsistent load due to casting from void* undefined behavior?


Here is what I see with the Clan and its disinfectants:

 bufhelp.h:146:29: runtime error: load of misaligned address 0x7fff04fdd0e1 for type 'const uintptr_t' (aka 'const unsigned long'), which requires 8 byte alignment 0x7fff04fdd0e1: note: pointer points here 00 00 00 66 66 6f 6f 62 61 72 34 32 46 4f 4f 42 41 52 31 37 66 6f 6f 62 61 72 34 33 46 4f 4f 42 ^ 

And here, where the cast is playing:

 buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len) { ... ldst = (uintptr_t *)(void *)dst; lsrc1 = (const uintptr_t *)(const void *)src1; lsrc2 = (const uintptr_t *)(const void *)src2; for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t)) *ldst++ = *lsrc1++ ^ *lsrc2++; ... } 

Related, but I do not believe the answer to the question above:

+6
source share
2 answers

Converting to an incorrectly aligned pointer is undefined, not just loading through that pointer (C11 (n1570) 6.3.2.3 p7):

A pointer to an object type can be converted to a pointer to another object type. If the resulting pointer is not correctly aligned [...] for the reference type, the behavior is undefined.

The code shown also violates strict anti-aliasing, since an object with a pointer cannot be declared as uintptr_t (the address will be correctly aligned otherwise).

To be standard, you can use unsigned char .

If uintptr_t digitized fragments should be copied for performance reasons, unsigned char can be used until the address is correctly aligned, and then another uintptr_t copy uintptr_t . This should be done through concatenation or through memcpy to avoid problems with an alias (Gcc can optimize memcpy calls if the size is constant). The last bytes may need to be copied using unsigned char again to avoid access outside the limits (reading bytes sizeof(uintptr_t)-1 past the array should not cause problems (Glibc does this in several places), but writing through dst can be written to another object). This may help restrict calculate the pointers used.

+6
source

I think the answer to your specific question is β€œyes” - although I'm not sure that it is specific to the broadcast itself, but to non-aligned pointers in general. The code internal to buf_xor () looks basically OK to me, so I would see what addresses are being passed.

It seems to me that you do not want you to call buf_xor () with inconsistent addresses. If this is not the case (if you call but_xor () everywhere with offset addresses), then I would make sure that uintptr_t is defined as the same thing (and, in particular, 64 bits wide based on your output), where buf_xor () compiled as well as where it is called.

One final personal note is that since your buf_xor () implementation requires consistent pointers as parameters for some processor / compiler implementations, you could probably save some future hassle by changing the signature to reflect this (change void * to uintptr_t *) - or change the implementation itself to correctly handle it manually, with inconsistent addresses on all architectures.

+1
source

Source: https://habr.com/ru/post/983409/


All Articles