mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-10-09 03:06:39 +00:00
fix(companion): signing takes the buffer it can get (#38)
CMD_SIGN_START promised the app 8K before a malloc it never checked. On the L1 the nRF52 heap has ~5K free from boot, so the malloc always failed and every CMD_SIGN_DATA answered ERR_CODE_BAD_STATE. Now it allocates first, halving down to 256 B, and reports the size it got; nothing at all is an error on SIGN_START itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1810,6 +1810,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
|||||||
clearPendingReqs();
|
clearPendingReqs();
|
||||||
next_ack_idx = 0;
|
next_ack_idx = 0;
|
||||||
sign_data = NULL;
|
sign_data = NULL;
|
||||||
|
sign_data_cap = 0;
|
||||||
dirty_contacts_expiry = 0;
|
dirty_contacts_expiry = 0;
|
||||||
memset(advert_paths, 0, sizeof(advert_paths));
|
memset(advert_paths, 0, sizeof(advert_paths));
|
||||||
memset(send_scope.key, 0, sizeof(send_scope.key));
|
memset(send_scope.key, 0, sizeof(send_scope.key));
|
||||||
@@ -2819,19 +2820,27 @@ void MyMesh::handleCmdFrame(size_t len) {
|
|||||||
writeErrFrame(ERR_CODE_NOT_FOUND); // bad channel_idx
|
writeErrFrame(ERR_CODE_NOT_FOUND); // bad channel_idx
|
||||||
}
|
}
|
||||||
} else if (cmd_frame[0] == CMD_SIGN_START) {
|
} else if (cmd_frame[0] == CMD_SIGN_START) {
|
||||||
out_frame[0] = RESP_CODE_SIGN_START;
|
|
||||||
out_frame[1] = 0; // reserved
|
|
||||||
uint32_t len = MAX_SIGN_DATA_LEN;
|
|
||||||
memcpy(&out_frame[2], &len, 4);
|
|
||||||
_serial->writeFrame(out_frame, 6);
|
|
||||||
|
|
||||||
if (sign_data) {
|
if (sign_data) {
|
||||||
free(sign_data);
|
free(sign_data);
|
||||||
}
|
}
|
||||||
sign_data = (uint8_t *)malloc(MAX_SIGN_DATA_LEN);
|
// A small MCU's heap (nRF52: ~70K, most of it taken at boot) may not have
|
||||||
|
// 8K in one block: take the biggest buffer we can get and tell the app its size,
|
||||||
|
// rather than promising 8K and failing every SIGN_DATA with BAD_STATE.
|
||||||
sign_data_len = 0;
|
sign_data_len = 0;
|
||||||
|
sign_data_cap = MAX_SIGN_DATA_LEN;
|
||||||
|
while ((sign_data = (uint8_t *)malloc(sign_data_cap)) == NULL && sign_data_cap > 256) {
|
||||||
|
sign_data_cap /= 2;
|
||||||
|
}
|
||||||
|
if (sign_data == NULL) {
|
||||||
|
writeErrFrame(ERR_CODE_BAD_STATE);
|
||||||
|
} else {
|
||||||
|
out_frame[0] = RESP_CODE_SIGN_START;
|
||||||
|
out_frame[1] = 0; // reserved
|
||||||
|
memcpy(&out_frame[2], &sign_data_cap, 4);
|
||||||
|
_serial->writeFrame(out_frame, 6);
|
||||||
|
}
|
||||||
} else if (cmd_frame[0] == CMD_SIGN_DATA && len > 1) {
|
} else if (cmd_frame[0] == CMD_SIGN_DATA && len > 1) {
|
||||||
if (sign_data == NULL || sign_data_len + (len - 1) > MAX_SIGN_DATA_LEN) {
|
if (sign_data == NULL || sign_data_len + (len - 1) > sign_data_cap) {
|
||||||
writeErrFrame(sign_data == NULL ? ERR_CODE_BAD_STATE : ERR_CODE_TABLE_FULL); // error: too long
|
writeErrFrame(sign_data == NULL ? ERR_CODE_BAD_STATE : ERR_CODE_TABLE_FULL); // error: too long
|
||||||
} else {
|
} else {
|
||||||
memcpy(&sign_data[sign_data_len], &cmd_frame[1], len - 1);
|
memcpy(&sign_data[sign_data_len], &cmd_frame[1], len - 1);
|
||||||
|
|||||||
@@ -633,6 +633,7 @@ private:
|
|||||||
uint8_t app_target_ver;
|
uint8_t app_target_ver;
|
||||||
uint8_t *sign_data;
|
uint8_t *sign_data;
|
||||||
uint32_t sign_data_len;
|
uint32_t sign_data_len;
|
||||||
|
uint32_t sign_data_cap; // what the malloc got: at most MAX_SIGN_DATA_LEN
|
||||||
unsigned long dirty_contacts_expiry;
|
unsigned long dirty_contacts_expiry;
|
||||||
unsigned long _bot_last_ch_reply_ms;
|
unsigned long _bot_last_ch_reply_ms;
|
||||||
unsigned long _bot_last_room_reply_ms;
|
unsigned long _bot_last_room_reply_ms;
|
||||||
|
|||||||
Reference in New Issue
Block a user