Skip to content

Alignment issue / undefined behavior? #516

Closed
@cbeck88

Description

@cbeck88

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

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions