Skip to content

Commit 196f579

Browse files
Copilotnetmindz
andcommitted
Implement correct metadata validation logic as requested in review comments
Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
1 parent 6149842 commit 196f579

File tree

1 file changed

+59
-61
lines changed

1 file changed

+59
-61
lines changed

wled00/wled_server.cpp

Lines changed: 59 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -426,12 +426,12 @@ void initServer()
426426
}
427427
if (!correctPIN || otaLock) return;
428428

429-
// Static variables to track release check status across chunks
429+
// Static variables to track release check status across chunks
430430
static bool releaseCheckPassed = false;
431431
static bool releaseCheckPending = true;
432432
static size_t totalBytesReceived = 0;
433433
static uint8_t* metadataBuffer = nullptr;
434-
static size_t metadataBufferSize = 0;
434+
static size_t metadataBufferUsed = 0;
435435

436436
if(!index){
437437
DEBUG_PRINTLN(F("OTA Update Start"));
@@ -445,7 +445,7 @@ void initServer()
445445
if (metadataBuffer) {
446446
free(metadataBuffer);
447447
metadataBuffer = nullptr;
448-
metadataBufferSize = 0;
448+
metadataBufferUsed = 0;
449449
}
450450

451451
// Check if user wants to skip validation
@@ -493,28 +493,21 @@ void initServer()
493493
}
494494

495495
// Track total bytes received across all chunks
496+
size_t chunkStartOffset = totalBytesReceived;
496497
totalBytesReceived += len;
497498

498-
// Check if we need to perform validation now
499-
if (releaseCheckPending) {
500-
// Calculate how much data we have after the metadata offset
501-
size_t dataAfterOffset = (totalBytesReceived > METADATA_OFFSET) ?
502-
(totalBytesReceived - METADATA_OFFSET) : 0;
499+
// Perform validation if we haven't done it yet and we have reached the metadata offset
500+
if (releaseCheckPending && totalBytesReceived > METADATA_OFFSET) {
503501

504-
if (dataAfterOffset > 0) {
505-
// We have data after the metadata offset, check if we can validate now
506-
size_t currentChunkStart = totalBytesReceived - len;
507-
size_t currentChunkAfterOffset = (currentChunkStart >= METADATA_OFFSET) ?
508-
0 : (METADATA_OFFSET - currentChunkStart);
502+
if (chunkStartOffset <= METADATA_OFFSET) {
503+
// Current chunk contains the metadata offset
504+
size_t offsetInChunk = METADATA_OFFSET - chunkStartOffset;
505+
size_t availableDataAfterOffset = len - offsetInChunk;
509506

510-
if (currentChunkStart <= METADATA_OFFSET &&
511-
(len - currentChunkAfterOffset) >= sizeof(wled_custom_desc_t)) {
512-
// We have enough data in the current chunk to validate
507+
if (availableDataAfterOffset >= sizeof(wled_custom_desc_t)) {
508+
// We have enough data in this chunk to validate immediately
513509
char errorMessage[128];
514-
uint8_t* validationData = data + currentChunkAfterOffset;
515-
size_t validationDataSize = len - currentChunkAfterOffset;
516-
517-
releaseCheckPassed = shouldAllowOTA(validationData, validationDataSize,
510+
releaseCheckPassed = shouldAllowOTA(data + offsetInChunk, availableDataAfterOffset,
518511
errorMessage, sizeof(errorMessage));
519512
releaseCheckPending = false;
520513

@@ -525,48 +518,53 @@ void initServer()
525518
} else {
526519
DEBUG_PRINTLN(F("OTA allowed: Release compatibility check passed"));
527520
}
528-
} else if (currentChunkStart < METADATA_OFFSET && totalBytesReceived > METADATA_OFFSET) {
529-
// Metadata spans across chunks, need to buffer exactly one callback worth
521+
522+
} else {
523+
// Not enough data in this chunk, buffer it for the next chunk
524+
metadataBuffer = (uint8_t*)malloc(len - offsetInChunk);
530525
if (!metadataBuffer) {
531-
// Calculate how much data we need from the previous chunk
532-
size_t prevChunkDataNeeded = METADATA_OFFSET - currentChunkStart;
533-
size_t totalBufferSize = prevChunkDataNeeded + len;
534-
535-
metadataBuffer = (uint8_t*)malloc(totalBufferSize);
536-
if (!metadataBuffer) {
537-
DEBUG_PRINTLN(F("OTA failed: Could not allocate metadata buffer"));
538-
request->send(500, FPSTR(CONTENT_TYPE_PLAIN), F("Out of memory for validation"));
539-
return;
540-
}
541-
542-
// For now, we'll validate on the next chunk when we have more data
543-
metadataBufferSize = totalBufferSize;
544-
memcpy(metadataBuffer, data, len);
545-
DEBUG_PRINTLN(F("Buffering metadata for validation on next chunk"));
526+
DEBUG_PRINTLN(F("OTA failed: Could not allocate metadata buffer"));
527+
request->send(500, FPSTR(CONTENT_TYPE_PLAIN), F("Out of memory for validation"));
528+
return;
529+
}
530+
memcpy(metadataBuffer, data + offsetInChunk, len - offsetInChunk);
531+
metadataBufferUsed = len - offsetInChunk;
532+
DEBUG_PRINTF_P(PSTR("Buffered %u bytes of metadata for next chunk\n"), metadataBufferUsed);
533+
}
534+
535+
} else if (metadataBuffer && metadataBufferUsed > 0) {
536+
// We have buffered metadata from previous chunk, combine with current chunk
537+
size_t totalMetadataSize = metadataBufferUsed + len;
538+
539+
if (totalMetadataSize >= sizeof(wled_custom_desc_t)) {
540+
// Create combined buffer for validation
541+
uint8_t* combinedBuffer = (uint8_t*)malloc(totalMetadataSize);
542+
if (!combinedBuffer) {
543+
DEBUG_PRINTLN(F("OTA failed: Could not allocate combined buffer"));
544+
request->send(500, FPSTR(CONTENT_TYPE_PLAIN), F("Out of memory for validation"));
545+
return;
546+
}
547+
548+
memcpy(combinedBuffer, metadataBuffer, metadataBufferUsed);
549+
memcpy(combinedBuffer + metadataBufferUsed, data, len);
550+
551+
char errorMessage[128];
552+
releaseCheckPassed = shouldAllowOTA(combinedBuffer, totalMetadataSize,
553+
errorMessage, sizeof(errorMessage));
554+
releaseCheckPending = false;
555+
556+
// Clean up buffers
557+
free(combinedBuffer);
558+
free(metadataBuffer);
559+
metadataBuffer = nullptr;
560+
metadataBufferUsed = 0;
561+
562+
if (!releaseCheckPassed) {
563+
DEBUG_PRINTF_P(PSTR("OTA declined: %s\n"), errorMessage);
564+
request->send(400, FPSTR(CONTENT_TYPE_PLAIN), errorMessage);
565+
return;
546566
} else {
547-
// We have buffered data from previous chunk, combine and validate
548-
memcpy(metadataBuffer + metadataBufferSize - len, data, len);
549-
550-
size_t metadataOffsetInBuffer = METADATA_OFFSET - (totalBytesReceived - metadataBufferSize);
551-
char errorMessage[128];
552-
553-
releaseCheckPassed = shouldAllowOTA(metadataBuffer + metadataOffsetInBuffer,
554-
metadataBufferSize - metadataOffsetInBuffer,
555-
errorMessage, sizeof(errorMessage));
556-
releaseCheckPending = false;
557-
558-
// Clean up buffer
559-
free(metadataBuffer);
560-
metadataBuffer = nullptr;
561-
metadataBufferSize = 0;
562-
563-
if (!releaseCheckPassed) {
564-
DEBUG_PRINTF_P(PSTR("OTA declined: %s\n"), errorMessage);
565-
request->send(400, FPSTR(CONTENT_TYPE_PLAIN), errorMessage);
566-
return;
567-
} else {
568-
DEBUG_PRINTLN(F("OTA allowed: Release compatibility check passed"));
569-
}
567+
DEBUG_PRINTLN(F("OTA allowed: Release compatibility check passed"));
570568
}
571569
}
572570
}
@@ -586,7 +584,7 @@ void initServer()
586584
if (metadataBuffer) {
587585
free(metadataBuffer);
588586
metadataBuffer = nullptr;
589-
metadataBufferSize = 0;
587+
metadataBufferUsed = 0;
590588
}
591589

592590
// Check if validation was still pending (shouldn't happen normally)

0 commit comments

Comments
 (0)