Ledmaps loading bugfix (wrong size, memory corruption)

* File.readbytesuntil does not terminate strings. So the string buffer needs to be filled with zero's before reading.
* fix crashes (mem corruption) when ledmap file has too many / too few entries.
* initialize unused map places with "identity" (same led) mapping

before fix:
> Reading LED map from /ledmap1.json
> ("width": 60edmap1.json)  ("height": 90edmap1.json)
> resetSegments 1 60x90
> allocLeds (0,0 to 60,90), 16200 from 0
> allocLeds (0,0 to 60,90), 16200 from 6
> deserializeMap 60 x 90 customMappingTable alloc 5400 from 0

after:
> Reading LED map from /ledmap1.json
> ("width": 60)  ("height": 9)
> resetSegments 1 60x9
> allocLeds (0,0 to 60,9), 1620 from 0
> allocLeds (0,0 to 60,9), 1620 from 6
> deserializeMap 60 x 9
> deserializemap customMappingTable alloc 540 from 0
This commit is contained in:
Frank
2024-02-20 15:10:25 +01:00
parent e833b898e4
commit 86b0eeafb7

View File

@@ -1424,7 +1424,7 @@ void WS2812FX::enumerateLedmaps() {
ledmapMaxSize = 0; ledmapMaxSize = 0;
ledMaps = 1; ledMaps = 1;
for (int i=1; i<10; i++) { for (int i=1; i<10; i++) {
char fileName[33]; char fileName[33] = {'\0'}; // WLEDMM ensure termination
snprintf_P(fileName, sizeof(fileName), PSTR("/ledmap%d.json"), i); snprintf_P(fileName, sizeof(fileName), PSTR("/ledmap%d.json"), i);
bool isFile = WLED_FS.exists(fileName); bool isFile = WLED_FS.exists(fileName);
@@ -2238,7 +2238,7 @@ void WS2812FX::loadCustomPalettes() {
bool WS2812FX::deserializeMap(uint8_t n) { bool WS2812FX::deserializeMap(uint8_t n) {
// 2D support creates its own ledmap (on the fly) if a ledmap.json exists it will overwrite built one. // 2D support creates its own ledmap (on the fly) if a ledmap.json exists it will overwrite built one.
char fileName[32]; char fileName[32] = {'\0'};
//WLEDMM: als support segment name ledmaps //WLEDMM: als support segment name ledmaps
bool isFile = false;; bool isFile = false;;
if (n<10) { if (n<10) {
@@ -2290,13 +2290,17 @@ bool WS2812FX::deserializeMap(uint8_t n) {
if (isMatrix) { if (isMatrix) {
//WLEDMM: read width and height //WLEDMM: read width and height
memset(fileName, 0, sizeof(fileName)); // clear old buffer - readBytesUntil() does not terminate strings !!!
f.find("\"width\":"); f.find("\"width\":");
f.readBytesUntil('\n', fileName, sizeof(fileName)); //hack: use fileName as we have this allocated already f.readBytesUntil('\n', fileName, sizeof(fileName)); //hack: use fileName as we have this allocated already
uint16_t maxWidth = atoi(fileName); uint16_t maxWidth = atoi(cleanUpName(fileName));
//DEBUG_PRINTF(" (\"width\": %s) ", fileName)
memset(fileName, 0, sizeof(fileName)); // clear old buffer
f.find("\"height\":"); f.find("\"height\":");
f.readBytesUntil('\n', fileName, sizeof(fileName)); f.readBytesUntil('\n', fileName, sizeof(fileName));
uint16_t maxHeight = atoi(fileName); uint16_t maxHeight = atoi(cleanUpName(fileName));
//DEBUG_PRINTF(" (\"height\": %s) \n", fileName)
//WLEDMM: support ledmap file properties width and height: if found change segment //WLEDMM: support ledmap file properties width and height: if found change segment
if (maxWidth * maxHeight > 0) { if (maxWidth * maxHeight > 0) {
@@ -2331,20 +2335,23 @@ bool WS2812FX::deserializeMap(uint8_t n) {
if (customMappingTable != nullptr) { if (customMappingTable != nullptr) {
customMappingSize = Segment::maxWidth * Segment::maxHeight; customMappingSize = Segment::maxWidth * Segment::maxHeight;
// WLEDMM reset mapping table before loading
//memset(customMappingTable, 0xFF, customMappingTableSize * sizeof(uint16_t)); // FFFF = no pixel
for (unsigned i=0; i<customMappingTableSize; i++) customMappingTable[i]=i; // "neutral" 1:1 mapping
//WLEDMM: find the map values //WLEDMM: find the map values
f.find("\"map\":["); f.find("\"map\":[");
uint16_t i=0; uint16_t i=0;
do { //for each element in the array do { //for each element in the array
int mapi = f.readStringUntil(',').toInt(); int mapi = f.readStringUntil(',').toInt();
// USER_PRINTF(", %d", mapi); // USER_PRINTF(", %d(%d)", mapi, i);
customMappingTable[i++] = (uint16_t) (mapi<0 ? 0xFFFFU : mapi); if (i < customMappingSize) customMappingTable[i++] = (uint16_t) (mapi<0 ? 0xFFFFU : mapi); // WLEDMM do not write past array bounds
} while (f.available()); } while (f.available());
loadedLedmap = n; loadedLedmap = n;
f.close(); f.close();
USER_PRINTF("Custom ledmap: %d\n", loadedLedmap); USER_PRINTF("Custom ledmap: %d size=%d\n", loadedLedmap, customMappingSize);
#ifdef WLED_DEBUG_MAPS #ifdef WLED_DEBUG_MAPS
for (uint16_t j=0; j<customMappingSize; j++) { // fixing a minor warning: declaration of 'i' shadows a previous local for (uint16_t j=0; j<customMappingSize; j++) { // fixing a minor warning: declaration of 'i' shadows a previous local
if (!(j%Segment::maxWidth)) DEBUG_PRINTLN(); if (!(j%Segment::maxWidth)) DEBUG_PRINTLN();