Skip to content

Missing 16-bit byte-swap definitions in generic endianness fallbacks #725

Description

@protz

The generic big-endian fallback (line 100) and generic little-endian fallback (line 128) define 32-bit and 64-bit byte-swap macros but omit all 16-bit variants. The macros load16_le, store16_le, load16_be, store16_be (lines 192-195) use le16toh/htole16/be16toh/htobe16 which will be undefined on these platforms.

Affected: Any non-Linux, non-macOS, non-BSD, non-Solaris, non-Windows platform using __BYTE_ORDER__ (e.g. bare-metal ARM with GCC, some RTOS environments, Emscripten on big-endian targets).

Test snippet:

// Compile with:
//   gcc -D__BYTE_ORDER__=__ORDER_BIG_ENDIAN__ -U__linux__ -U__APPLE__ \
//       -U__FreeBSD__ -U__sun__ -U_MSC_VER -c test.c
#include "krml/lowstar_endianness.h"
int main(void) {
    uint8_t buf[2] = {0x01, 0x02};
    uint16_t val = load16_le(buf);  // ERROR: 'le16toh' undeclared
    return 0;
}

Suggested fix -- add to the big-endian fallback block (after line 100):

#  define htobe16(x) (x)
#  define be16toh(x) (x)
#  define htole16(x)                                                           \
    ((uint16_t)((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00)))
#  define le16toh(x) (htole16((x)))

And to the little-endian fallback block (after line 128):

#  define htole16(x) (x)
#  define le16toh(x) (x)
#  define htobe16(x)                                                           \
    ((uint16_t)((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00)))
#  define be16toh(x) (htobe16((x)))

This issue was found by Claude (Opus 4.6)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions