From 4d2051ad8f7d969dd46267df8ae0dc5292baa3a6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 18 Feb 2026 08:16:55 -0600 Subject: [PATCH] no widen --- esphome/components/api/proto.h | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index bb8cad7b70a..ec695b44f02 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -108,9 +108,12 @@ class ProtoVarInt { #ifdef ESPHOME_DEBUG_API assert(consumed != nullptr); #endif - // 32-bit phase: bytes 0-3 (shifts 0, 7, 14, 21 — all native on 32-bit platforms) + // 32-bit phase: bytes 0-4 cover all uint32 varint values + // Byte 4 shift (28) may truncate upper 3 bits in uint32, but those are + // always zero for valid uint32 values; parse_wide re-processes byte 4 + // with full 64-bit arithmetic when the varint continues past byte 4. uint32_t result32 = 0; - uint32_t limit = std::min(len, uint32_t(4)); + uint32_t limit = std::min(len, uint32_t(5)); for (uint32_t i = 0; i < limit; i++) { uint8_t val = buffer[i]; result32 |= uint32_t(val & 0x7F) << (i * 7); @@ -119,23 +122,12 @@ class ProtoVarInt { return ProtoVarInt(result32); } } - // Byte 4: handles uint32 values >= 2^28 that need 5 varint bytes - // Only lower 4 bits contribute to bits 28-31 of the uint32 result - if (len > 4) { - uint8_t val = buffer[4]; - result32 |= uint32_t(val & 0x0F) << 28; - if ((val & 0x80) == 0) { - *consumed = 5; - return ProtoVarInt(result32); - } - // Varint continues past byte 4 — needs 64-bit (BLE addresses etc.) + // 64-bit phase for values > 32 bits (BLE addresses etc.) #ifdef USE_API_VARINT64 - return parse_wide(buffer, len, consumed, result32); + return parse_wide(buffer, len, consumed, result32); #else - return {}; -#endif - } return {}; +#endif } #ifdef USE_API_VARINT64