@@ -13,10 +13,10 @@ bool extractWledCustomDesc(const uint8_t* binaryData, size_t dataSize, wled_cust
13
13
14
14
// Search in first 8KB only. This range was chosen because:
15
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)
16
+ // - ESP8266 .ver_number sections also appear early (typically within first 1-2KB)
17
17
// - 8KB provides ample coverage for metadata discovery while minimizing processing time
18
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
19
+ // - Analysis of typical WLED binary layouts shows metadata appears well within this range
20
20
const size_t search_limit = min (dataSize, (size_t )8192 );
21
21
22
22
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
41
41
// Valid structure found - copy entire structure
42
42
memcpy (extractedDesc, custom_desc, sizeof (wled_custom_desc_t ));
43
43
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 " ),
46
45
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
51
46
return true ;
52
47
}
53
48
}
@@ -57,59 +52,61 @@ bool extractWledCustomDesc(const uint8_t* binaryData, size_t dataSize, wled_cust
57
52
}
58
53
59
54
bool 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 ) {
61
65
return false ;
62
66
}
63
67
64
68
// Simple string comparison - releases must match exactly
65
- bool match = strcmp (releaseString, extractedRelease ) == 0 ;
69
+ bool match = strcmp (releaseString, safeRelease ) == 0 ;
66
70
67
71
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" );
69
73
70
74
return match;
71
75
}
72
76
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 ) {
74
78
// Clear error message
75
- if (errorMessage) {
79
+ if (errorMessage && errorMessageLen > 0 ) {
76
80
errorMessage[0 ] = ' \0 ' ;
77
81
}
78
82
79
83
// Ensure our custom description structure is referenced (prevents optimization)
80
84
const wled_custom_desc_t * local_desc = getWledCustomDesc ();
81
85
(void )local_desc; // Suppress unused variable warning
82
86
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
-
89
87
// Try to extract WLED structure directly from binary data
90
88
wled_custom_desc_t extractedDesc;
91
89
bool hasCustomDesc = extractWledCustomDesc (binaryData, dataSize, &extractedDesc);
92
90
93
91
if (!hasCustomDesc) {
94
92
// 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 ' ;
97
97
}
98
- DEBUG_PRINTLN (F (" OTA declined: No custom description found" ));
99
98
return false ;
100
99
}
101
100
102
101
// Validate compatibility using extracted release name
103
102
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." ,
106
105
releaseString, extractedDesc.release_name );
106
+ errorMessage[errorMessageLen - 1 ] = ' \0 ' ; // Ensure null termination
107
107
}
108
- DEBUG_PRINTF_P (PSTR (" OTA declined: Release mismatch current='%s', uploaded='%s'\n " ),
109
- releaseString, extractedDesc.release_name );
110
108
return false ;
111
109
}
112
110
113
- DEBUG_PRINTLN (F (" OTA allowed: Release names match" ));
114
111
return true ;
115
112
}
0 commit comments