From ba362a7c95e9cffce5b6a39da32b95f1c9f3bd3e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 24 Apr 2026 21:43:13 -0500 Subject: [PATCH] [api] Narrow 48-bit MAC varint fast path to values < 2^48 Per Copilot review: encode_varint_raw_48bit and calc_uint64_48bit_force would silently truncate bits 48..63 if ever called with a uint64 that doesn't fit in 48 bits. Real MAC addresses always fit, but since the helpers are exposed and the (mac_address) option is generic, narrow the fast path to [1<<42, 1<<48) so values outside that range fall back to the general encoder/size helpers. Re-verified byte-identical output and decoder round-trip across the 1<<48 boundary and all bit positions up to 63. --- esphome/components/api/proto.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index d274c89537..30efdfbb61 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -344,11 +344,13 @@ class ProtoEncode { } /// Encode a 48-bit MAC address (stored in a uint64) as varint. /// Real MAC addresses occupy the full 48 bits (OUI in upper 24), so the - /// fast path -- any non-zero bit in bits [42..47] -- emits exactly 7 bytes - /// with no per-byte branch. Falls back to the general loop otherwise. + /// fast path -- any non-zero bit in bits [42..47] with value fitting in + /// 48 bits -- emits exactly 7 bytes with no per-byte branch. Values outside + /// [1<<42, 1<<48) fall back to the general encoder to preserve correctness + /// if this helper is ever misapplied to a non-MAC uint64. static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_48bit(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint64_t value) { - if (value >= (1ULL << 42)) [[likely]] { + if (value >= (1ULL << 42) && value < (1ULL << 48)) [[likely]] { PROTO_ENCODE_CHECK_BOUNDS(pos, 7); pos[0] = static_cast(value | 0x80); pos[1] = static_cast((value >> 7) | 0x80); @@ -838,11 +840,12 @@ class ProtoSize { return field_id_size + varint(value); } /// 48-bit MAC address variant: matches encode_varint_raw_48bit's fast path. - /// When value uses any of bits [42..47] the encoded varint is 7 bytes; - /// otherwise fall back to the general size calculation. + /// When value is in [1<<42, 1<<48) the encoded varint is 7 bytes; values + /// outside that range fall back to the general size calculation so the + /// result stays correct if this helper is ever misapplied. static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE calc_uint64_48bit_force(uint32_t field_id_size, uint64_t value) { - return field_id_size + (value >= (1ULL << 42) ? 7 : varint(value)); + return field_id_size + ((value >= (1ULL << 42) && value < (1ULL << 48)) ? 7 : varint(value)); } static constexpr uint32_t calc_length(uint32_t field_id_size, size_t len) { return len ? field_id_size + varint(static_cast(len)) + static_cast(len) : 0;