Closed
Description
In recent tests, my program began crashing in release mode, though not in debug mode. When running my program in release mode using clang -fsanitize=undefined
, I get no crashes and the following error reports instead in websocketpp:
lib/websocketpp-0.6.0+/include/websocketpp/frame.hpp:775:38: runtime error: load of misaligned address 0x0000021cee9e for type 'size_t', which requires 8 byte alignment
0x0000021cee9e: note: pointer points here
76 68 87 64 0d 62 dc 55 2b 48 ba 44 54 19 f2 01 04 11 d8 16 19 07 ea 17 54 44 8d 3f 44 35 a7 59
The code in question is here:
inline size_t word_mask_circ(uint8_t * input, uint8_t * output, size_t length,
size_t prepared_key)
{
size_t n = length / sizeof(size_t); // whole words
size_t l = length - (n * sizeof(size_t)); // remaining bytes
size_t * input_word = reinterpret_cast<size_t *>(input);
size_t * output_word = reinterpret_cast<size_t *>(output);
// mask word by word
for (size_t i = 0; i < n; i++) {
output_word[i] = input_word[i] ^ prepared_key;
}
// mask partial word at the end
size_t start = length - l;
uint8_t * byte_key = reinterpret_cast<uint8_t *>(&prepared_key);
for (size_t i = 0; i < l; ++i) {
output[start+i] = input[start+i] ^ byte_key[i];
}
return circshift_prepared_key(prepared_key,l);
}
I currently am working around this by using byte-by-byte masking for the entire range, skipping the cast to size_t
, even if it will be slower.
inline size_t word_mask_circ(uint8_t * input, uint8_t * output, size_t length,
size_t prepared_key)
{
size_t n = length / sizeof(size_t); // whole words
size_t l = length - (n * sizeof(size_t)); // remaining bytes
uint8_t * byte_key = reinterpret_cast<uint8_t *>(&prepared_key);
for (size_t i = 0; i < length; ++i) {
output[i] = input[i] ^ byte_key[i % sizeof(size_t)];
}
return circshift_prepared_key(prepared_key,l);
}
I also get a warning here about using shift exponent which is too large:
lib/websocketpp-0.6.0+/include/websocketpp/frame.hpp:614:36: runtime error: shift exponent 64 is too large for 64-bit type 'long unsigned int'
The code in question is:
inline size_t circshift_prepared_key(size_t prepared_key, size_t offset) {
if (lib::net::is_little_endian()) {
size_t temp = prepared_key << (sizeof(size_t)-offset)*8;
return (prepared_key >> offset*8) | temp;
} else {
size_t temp = prepared_key >> (sizeof(size_t)-offset)*8;
return (prepared_key << offset*8) | temp;
}
}
I currently am working around this by testing the value of offset like so:
inline size_t circshift_prepared_key(size_t prepared_key, size_t offset) {
if (!offset) { return prepared_key; }
if (lib::net::is_little_endian()) {
size_t temp = prepared_key << (sizeof(size_t)-offset)*8;
return (prepared_key >> offset*8) | temp;
} else {
size_t temp = prepared_key >> (sizeof(size_t)-offset)*8;
return (prepared_key << offset*8) | temp;
}
}
The patches I made seem to prevent the crashes and things seem to be working normally, but I would appreciate some guidance from upstream 😄
Metadata
Metadata
Assignees
Labels
No labels