Skip to content

Commit ffe8eec

Browse files
committed
validate advert payload length before parsing
The ADVERT handler copied pub_key, timestamp, and signature from the payload before checking whether payload_len was large enough to contain them. With a short payload, the memcpy operations read uninitialized data from within the payload buffer. Move the bounds check before any parsing so undersized adverts are rejected immediately. The minimum required is PUB_KEY_SIZE + 4 + SIGNATURE_SIZE (100 bytes).
1 parent e6e87fb commit ffe8eec

1 file changed

Lines changed: 7 additions & 3 deletions

File tree

src/Mesh.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,20 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
241241
}
242242
case PAYLOAD_TYPE_ADVERT: {
243243
int i = 0;
244+
int min_advert_len = PUB_KEY_SIZE + 4 + SIGNATURE_SIZE;
245+
if (pkt->payload_len < min_advert_len) {
246+
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete advertisement packet, payload_len=%d", getLogDateTime(), (int)pkt->payload_len);
247+
break;
248+
}
249+
244250
Identity id;
245251
memcpy(id.pub_key, &pkt->payload[i], PUB_KEY_SIZE); i += PUB_KEY_SIZE;
246252

247253
uint32_t timestamp;
248254
memcpy(&timestamp, &pkt->payload[i], 4); i += 4;
249255
const uint8_t* signature = &pkt->payload[i]; i += SIGNATURE_SIZE;
250256

251-
if (i > pkt->payload_len) {
252-
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete advertisement packet", getLogDateTime());
253-
} else if (self_id.matches(id.pub_key)) {
257+
if (self_id.matches(id.pub_key)) {
254258
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): receiving SELF advert packet", getLogDateTime());
255259
} else if (!_tables->hasSeen(pkt)) {
256260
uint8_t* app_data = &pkt->payload[i];

0 commit comments

Comments
 (0)