@@ -13,10 +13,10 @@ bool extractWledCustomDesc(const uint8_t* binaryData, size_t dataSize, wled_cust
1313
1414 // Search in first 8KB only. This range was chosen because:
1515 // - 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)
16+ // - ESP8266 .ver_number sections also appear early (typically within first 1-2KB)
1717 // - 8KB provides ample coverage for metadata discovery while minimizing processing time
1818 // - 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
19+ // - Analysis of typical WLED binary layouts shows metadata appears well within this range
2020 const size_t search_limit = min (dataSize, (size_t )8192 );
2121
2222 for (size_t offset = 0 ; offset <= search_limit - sizeof (wled_custom_desc_t ); offset++) {
@@ -41,13 +41,8 @@ bool extractWledCustomDesc(const uint8_t* binaryData, size_t dataSize, wled_cust
4141 // Valid structure found - copy entire structure
4242 memcpy (extractedDesc, custom_desc, sizeof (wled_custom_desc_t ));
4343
44- #ifdef ESP32
45- DEBUG_PRINTF_P (PSTR (" Extracted ESP32 WLED structure from .rodata.wled_desc section at offset %u: '%s'\n " ),
44+ DEBUG_PRINTF_P (PSTR (" Extracted WLED structure at offset %u: '%s'\n " ),
4645 offset, extractedDesc->release_name );
47- #else
48- DEBUG_PRINTF_P (PSTR (" Extracted ESP8266 WLED structure from .ver_number section at offset %u: '%s'\n " ),
49- offset, extractedDesc->release_name );
50- #endif
5146 return true ;
5247 }
5348 }
@@ -57,59 +52,61 @@ bool extractWledCustomDesc(const uint8_t* binaryData, size_t dataSize, wled_cust
5752}
5853
5954bool validateReleaseCompatibility (const char * extractedRelease) {
60- if (!extractedRelease || strlen (extractedRelease) == 0 ) {
55+ if (!extractedRelease) {
56+ return false ;
57+ }
58+
59+ // Ensure extractedRelease is properly null terminated (guard against fixed-length buffer issues)
60+ char safeRelease[WLED_RELEASE_NAME_MAX_LEN];
61+ strncpy (safeRelease, extractedRelease, WLED_RELEASE_NAME_MAX_LEN - 1 );
62+ safeRelease[WLED_RELEASE_NAME_MAX_LEN - 1 ] = ' \0 ' ;
63+
64+ if (strlen (safeRelease) == 0 ) {
6165 return false ;
6266 }
6367
6468 // Simple string comparison - releases must match exactly
65- bool match = strcmp (releaseString, extractedRelease ) == 0 ;
69+ bool match = strcmp (releaseString, safeRelease ) == 0 ;
6670
6771 DEBUG_PRINTF_P (PSTR (" Release compatibility check: current='%s', uploaded='%s', match=%s\n " ),
68- releaseString, extractedRelease , match ? " YES" : " NO" );
72+ releaseString, safeRelease , match ? " YES" : " NO" );
6973
7074 return match;
7175}
7276
73- bool shouldAllowOTA (const uint8_t * binaryData, size_t dataSize, bool skipValidation, char * errorMessage) {
77+ bool shouldAllowOTA (const uint8_t * binaryData, size_t dataSize, char * errorMessage, size_t errorMessageLen ) {
7478 // Clear error message
75- if (errorMessage) {
79+ if (errorMessage && errorMessageLen > 0 ) {
7680 errorMessage[0 ] = ' \0 ' ;
7781 }
7882
7983 // Ensure our custom description structure is referenced (prevents optimization)
8084 const wled_custom_desc_t * local_desc = getWledCustomDesc ();
8185 (void )local_desc; // Suppress unused variable warning
8286
83- // If user chose to skip validation, allow OTA immediately
84- if (skipValidation) {
85- DEBUG_PRINTLN (F (" OTA release check bypassed by user" ));
86- return true ;
87- }
88-
8987 // Try to extract WLED structure directly from binary data
9088 wled_custom_desc_t extractedDesc;
9189 bool hasCustomDesc = extractWledCustomDesc (binaryData, dataSize, &extractedDesc);
9290
9391 if (!hasCustomDesc) {
9492 // No custom description - this could be a legacy binary
95- if (errorMessage) {
96- strcpy (errorMessage, " This firmware file is missing compatibility metadata. Enable 'Ignore firmware validation' to proceed anyway." );
93+ if (errorMessage && errorMessageLen > 0 ) {
94+ const char * msg = " This firmware file is missing compatibility metadata. Enable 'Ignore firmware validation' to proceed anyway." ;
95+ strncpy (errorMessage, msg, errorMessageLen - 1 );
96+ errorMessage[errorMessageLen - 1 ] = ' \0 ' ;
9797 }
98- DEBUG_PRINTLN (F (" OTA declined: No custom description found" ));
9998 return false ;
10099 }
101100
102101 // Validate compatibility using extracted release name
103102 if (!validateReleaseCompatibility (extractedDesc.release_name )) {
104- if (errorMessage) {
105- snprintf (errorMessage, 127 , " Firmware compatibility mismatch: current='%s', uploaded='%s'. Enable 'Ignore firmware validation' to proceed anyway." ,
103+ if (errorMessage && errorMessageLen > 0 ) {
104+ snprintf (errorMessage, errorMessageLen , " Firmware compatibility mismatch: current='%s', uploaded='%s'. Enable 'Ignore firmware validation' to proceed anyway." ,
106105 releaseString, extractedDesc.release_name );
106+ errorMessage[errorMessageLen - 1 ] = ' \0 ' ; // Ensure null termination
107107 }
108- DEBUG_PRINTF_P (PSTR (" OTA declined: Release mismatch current='%s', uploaded='%s'\n " ),
109- releaseString, extractedDesc.release_name );
110108 return false ;
111109 }
112110
113- DEBUG_PRINTLN (F (" OTA allowed: Release names match" ));
114111 return true ;
115112}
0 commit comments