What changed, and why it matters
This commit fixes a small but real bug in how the BitBox02 hardware wallet tells its Bluetooth chip what name to broadcast. The code that copies the device name into a fixed-size buffer correctly limited the copy to 63 bytes, but then accidentally reported the original, possibly longer length to the next processing step. That mismatch could make the Bluetooth formatting function read past the end of the 64-byte buffer, leaking nearby memory or crashing the device. The fix makes the reported length match the actual copied length.
Treat as a low-severity security hardening fix. Verify that SetDeviceName validation is enforced on all code paths and that no caller can pass a name longer than 63 bytes. Consider adding a static or runtime assertion that payload_name_len <= sizeof(payload) - 1.
Security signals we found
Length mismatch between memcpy size and reported buffer length
Potential out-of-bounds read from a stack buffer
Information disclosure via leaked stack memory in Bluetooth advertisement payload
Fix is defensive/hardening even if current API validation keeps names under 63 bytes
Evidence from the diff
In da14531_set_name(), a 64-byte stack payload array receives a one-byte command header plus up to sizeof(payload)-1 bytes of the device name. The memcpy correctly truncated name_len, but the da14531_protocol_format() call was passed 1 + name_len as the payload length. If name_len exceeded 63, that length would exceed the real payload size, causing the protocol formatter to read uninitialized/garbage bytes beyond payload[63]. The patch stores the truncated length in payload_name_len and uses 1 + payload_name_len consistently.
Changed components
src/da14531/da14531.cda14531_set_name()Bluetooth LE device name configuration on BitBox02Inspect captured patch +7 / −2
diff --git a/src/da14531/da14531.c b/src/da14531/da14531.c
index de2f714..cd54505 100644
--- a/src/da14531/da14531.c
+++ b/src/da14531/da14531.c
@@ -62,11 +62,16 @@ void da14531_set_name(const char* name, struct RustByteQueue* uart_out)
{
size_t name_len = strlen(name);
uint8_t payload[64] = {0};
+ size_t payload_name_len = MIN(name_len, sizeof(payload) - 1);
payload[0] = CTRL_CMD_DEVICE_NAME;
- memcpy(&payload[1], name, MIN(name_len, sizeof(payload) - 1));
+ memcpy(&payload[1], name, payload_name_len);
uint8_t tmp[12 + sizeof(payload) * 2];
uint16_t tmp_len = da14531_protocol_format(
- &tmp[0], sizeof(tmp), DA14531_PROTOCOL_PACKET_TYPE_CTRL_DATA, &payload[0], 1 + name_len);
+ &tmp[0],
+ sizeof(tmp),
+ DA14531_PROTOCOL_PACKET_TYPE_CTRL_DATA,
+ &payload[0],
+ 1 + payload_name_len);
ASSERT(tmp_len <= sizeof(tmp));
for (int i = 0; i < tmp_len; i++) {
rust_bytequeue_put(uart_out, tmp[i]);
Why this scored 35/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.