66#include < esp_ota_ops.h>
77#endif
88
9- // Same hash function used at compile time (must match wled_custom_desc.cpp)
10- static uint32_t djb2_hash (const char * str) {
11- uint32_t hash = 5381 ;
12- while (*str) {
13- hash = ((hash << 5 ) + hash) + *str++;
14- }
15- return hash;
16- }
17-
18- bool extractReleaseFromCustomDesc (const uint8_t * binaryData, size_t dataSize, char * extractedRelease) {
19- if (!binaryData || !extractedRelease || dataSize < 64 ) {
9+ bool extractWledCustomDesc (const uint8_t * binaryData, size_t dataSize, wled_custom_desc_t * extractedDesc) {
10+ if (!binaryData || !extractedDesc || dataSize < 64 ) {
2011 return false ;
2112 }
2213
23- // Search in first 8KB only - ESP32 .rodata.wled_desc and ESP8266 .ver_number
24- // sections appear early in binary. 8KB should be sufficient for metadata discovery
25- // while minimizing processing time for large firmware files.
14+ // Search in first 8KB only. This range was chosen because:
15+ // - ESP32 .rodata.wled_desc sections appear early in the binary (typically within first 2-4KB)
16+ // - ESP8266 .ver_number sections also appear early (typically within first 1-2KB)
17+ // - 8KB provides ample coverage for metadata discovery while minimizing processing time
18+ // - Larger firmware files (>1MB) would take significantly longer to process with full search
19+ // - Real-world testing shows all valid metadata appears well within this range
2620 const size_t search_limit = min (dataSize, (size_t )8192 );
2721
2822 for (size_t offset = 0 ; offset <= search_limit - sizeof (wled_custom_desc_t ); offset++) {
@@ -37,23 +31,22 @@ bool extractReleaseFromCustomDesc(const uint8_t* binaryData, size_t dataSize, ch
3731 continue ;
3832 }
3933
40- // Validate hash using same algorithm as compile-time
41- uint32_t expected_hash = djb2_hash (custom_desc->release_name );
34+ // Validate hash using runtime function
35+ uint32_t expected_hash = djb2_hash_runtime (custom_desc->release_name );
4236 if (custom_desc->crc32 != expected_hash) {
4337 DEBUG_PRINTF_P (PSTR (" Found WLED structure at offset %u but hash mismatch\n " ), offset);
4438 continue ;
4539 }
4640
47- // Valid structure found
48- strncpy (extractedRelease, custom_desc->release_name , WLED_RELEASE_NAME_MAX_LEN - 1 );
49- extractedRelease[WLED_RELEASE_NAME_MAX_LEN - 1 ] = ' \0 ' ;
41+ // Valid structure found - copy entire structure
42+ memcpy (extractedDesc, custom_desc, sizeof (wled_custom_desc_t ));
5043
5144 #ifdef ESP32
52- DEBUG_PRINTF_P (PSTR (" Extracted ESP32 release name from .rodata.wled_desc section at offset %u: '%s'\n " ),
53- offset, extractedRelease );
45+ DEBUG_PRINTF_P (PSTR (" Extracted ESP32 WLED structure from .rodata.wled_desc section at offset %u: '%s'\n " ),
46+ offset, extractedDesc-> release_name );
5447 #else
55- DEBUG_PRINTF_P (PSTR (" Extracted ESP8266 release name from .ver_number section at offset %u: '%s'\n " ),
56- offset, extractedRelease );
48+ DEBUG_PRINTF_P (PSTR (" Extracted ESP8266 WLED structure from .ver_number section at offset %u: '%s'\n " ),
49+ offset, extractedDesc-> release_name );
5750 #endif
5851 return true ;
5952 }
@@ -87,33 +80,33 @@ bool shouldAllowOTA(const uint8_t* binaryData, size_t dataSize, bool skipValidat
8780 const wled_custom_desc_t * local_desc = getWledCustomDesc ();
8881 (void )local_desc; // Suppress unused variable warning
8982
90- // If user chose to ignore release check , allow OTA
83+ // If user chose to skip validation , allow OTA immediately
9184 if (skipValidation) {
9285 DEBUG_PRINTLN (F (" OTA release check bypassed by user" ));
9386 return true ;
9487 }
9588
96- // Try to extract release name directly from binary data
97- char extractedRelease[WLED_RELEASE_NAME_MAX_LEN] ;
98- bool hasCustomDesc = extractReleaseFromCustomDesc (binaryData, dataSize, extractedRelease );
89+ // Try to extract WLED structure directly from binary data
90+ wled_custom_desc_t extractedDesc ;
91+ bool hasCustomDesc = extractWledCustomDesc (binaryData, dataSize, &extractedDesc );
9992
10093 if (!hasCustomDesc) {
10194 // No custom description - this could be a legacy binary
10295 if (errorMessage) {
103- strcpy (errorMessage, " Binary has no release compatibility metadata. Check 'Ignore validation' to proceed." );
96+ strcpy (errorMessage, " This firmware file is missing compatibility metadata. Enable 'Ignore firmware validation' to proceed anyway ." );
10497 }
105- DEBUG_PRINTLN (F (" OTA blocked : No custom description found" ));
98+ DEBUG_PRINTLN (F (" OTA declined : No custom description found" ));
10699 return false ;
107100 }
108101
109102 // Validate compatibility using extracted release name
110- if (!validateReleaseCompatibility (extractedRelease )) {
103+ if (!validateReleaseCompatibility (extractedDesc. release_name )) {
111104 if (errorMessage) {
112- snprintf (errorMessage, 127 , " Release mismatch: current='%s', uploaded='%s'. Check 'Ignore validation' to proceed." ,
113- releaseString, extractedRelease );
105+ snprintf (errorMessage, 127 , " Firmware compatibility mismatch: current='%s', uploaded='%s'. Enable 'Ignore firmware validation' to proceed anyway ." ,
106+ releaseString, extractedDesc. release_name );
114107 }
115- DEBUG_PRINTF_P (PSTR (" OTA blocked : Release mismatch current='%s', uploaded='%s'\n " ),
116- releaseString, extractedRelease );
108+ DEBUG_PRINTF_P (PSTR (" OTA declined : Release mismatch current='%s', uploaded='%s'\n " ),
109+ releaseString, extractedDesc. release_name );
117110 return false ;
118111 }
119112
0 commit comments