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;
ledMaps = 1;
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);
bool isFile = WLED_FS.exists(fileName);
@@ -2238,7 +2238,7 @@ void WS2812FX::loadCustomPalettes() {
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.
char fileName[32];
char fileName[32] = {'\0'};
//WLEDMM: als support segment name ledmaps
bool isFile = false;;
if (n<10) {
@@ -2290,13 +2290,17 @@ bool WS2812FX::deserializeMap(uint8_t n) {
if (isMatrix) {
//WLEDMM: read width and height
memset(fileName, 0, sizeof(fileName)); // clear old buffer - readBytesUntil() does not terminate strings !!!
f.find("\"width\":");
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.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
if (maxWidth * maxHeight > 0) {
@@ -2331,20 +2335,23 @@ bool WS2812FX::deserializeMap(uint8_t n) {
if (customMappingTable != nullptr) {
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
f.find("\"map\":[");
uint16_t i=0;
do { //for each element in the array
int mapi = f.readStringUntil(',').toInt();
// USER_PRINTF(", %d", mapi);
customMappingTable[i++] = (uint16_t) (mapi<0 ? 0xFFFFU : mapi);
// USER_PRINTF(", %d(%d)", mapi, i);
if (i < customMappingSize) customMappingTable[i++] = (uint16_t) (mapi<0 ? 0xFFFFU : mapi); // WLEDMM do not write past array bounds
} while (f.available());
loadedLedmap = n;
f.close();
USER_PRINTF("Custom ledmap: %d\n", loadedLedmap);
USER_PRINTF("Custom ledmap: %d size=%d\n", loadedLedmap, customMappingSize);
#ifdef WLED_DEBUG_MAPS
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();