Skip to content

Commit c2d755b

Browse files
authored
Merge pull request #326 from MoonModules/dxm_hotfix
hotfix for DMX-serial output (prevents random crashes caused by array bounds violations) * Align ESPDMX and SparkFunDMX with upstream code * Prevent driver compilation when WLED_ENABLE_DMX is not set (saves ~1KB RAM) * Protect against writing outside of array bounds * Align start byte handling between ESPDMX and SparkFunDMX driver.
2 parents f0531cd + 57d63b7 commit c2d755b

File tree

5 files changed

+28
-20
lines changed

5 files changed

+28
-20
lines changed

wled00/dmx_input.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "wled.h"
22

33
#ifdef WLED_ENABLE_DMX_INPUT
4-
#pragma message "DMX physical input driver enabled"
4+
#pragma message "DMX physical input driver (esp-dmx) enabled"
55

66
#ifdef ESP8266
77
#error DMX input is only supported on ESP32

wled00/dmx_output.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212

1313
#ifdef WLED_ENABLE_DMX
14-
#pragma message "DMX network output enabled"
14+
#pragma message "DMX output enabled"
1515

1616
#define MAX_DMX_RATE 44 // max DMX update rate in Hz
1717

@@ -99,7 +99,7 @@ void handleDMXOutput()
9999
}
100100

101101
void initDMXOutput() {
102-
#ifdef ESP8266
102+
#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2)
103103
dmx.init(512); // initialize with bus length
104104
#else
105105
dmx.initWrite(512); // initialize with bus length

wled00/src/dependencies/dmx/ESPDMX.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
// - - - - -
1212

1313
/* ----- LIBRARIES ----- */
14-
#ifdef ESP8266
14+
#if defined(WLED_ENABLE_DMX) && (defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2))
1515

1616
#include <Arduino.h>
1717

1818
#include "ESPDMX.h"
1919

20+
#pragma message "using ESPDMX"
2021

2122

2223
#define dmxMaxChannel 512
@@ -30,8 +31,8 @@
3031
bool dmxStarted = false;
3132
int sendPin = 2; //default on ESP8266
3233

33-
//DMX value array and size. Entry 0 will hold startbyte
34-
uint8_t dmxDataStore[dmxMaxChannel] = {};
34+
//DMX value array and size. Entry 0 will hold startbyte, so we need 512+1 elements
35+
uint8_t dmxDataStore[dmxMaxChannel+1] = {};
3536
int channelSize;
3637

3738

@@ -72,6 +73,7 @@ void DMXESPSerial::write(int Channel, uint8_t value) {
7273

7374
if (Channel < 1) Channel = 1;
7475
if (Channel > channelSize) Channel = channelSize;
76+
if (Channel > dmxMaxChannel) Channel = dmxMaxChannel; // WLEDMM protect against array bounds violation
7577
if (value < 0) value = 0;
7678
if (value > 255) value = 255;
7779

@@ -98,12 +100,12 @@ void DMXESPSerial::update() {
98100
//send data
99101
Serial1.begin(DMXSPEED, DMXFORMAT);
100102
digitalWrite(sendPin, LOW);
101-
Serial1.write(dmxDataStore, channelSize);
103+
Serial1.write(dmxDataStore, min(dmxMaxChannel+1, channelSize+1));
102104
Serial1.flush();
103105
delay(1);
104106
Serial1.end();
105107
}
106108

107109
// Function to update the DMX bus
108110

109-
#endif
111+
#endif

wled00/src/dependencies/dmx/SparkFunDMX.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ Distributed as-is; no warranty is given.
1414
******************************************************************************/
1515

1616
/* ----- LIBRARIES ----- */
17-
#if defined(ARDUINO_ARCH_ESP32)
17+
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_ENABLE_DMX)
1818

1919
#include <Arduino.h>
2020
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
2121

2222
#include "SparkFunDMX.h"
2323
#include <HardwareSerial.h>
2424

25+
#pragma message "using SparkFunDMX"
26+
2527
#define dmxMaxChannel 512
2628
#define defaultMax 32
2729

@@ -34,8 +36,8 @@ static const int enablePin = -1; // disable the enable pin because it is not ne
3436
static const int rxPin = -1; // disable the receiving pin because it is not needed - softhack007: Pin=-1 means "use default" not "disable"
3537
static const int txPin = 2; // transmit DMX data over this pin (default is pin 2)
3638

37-
//DMX value array and size. Entry 0 will hold startbyte
38-
static uint8_t dmxData[dmxMaxChannel] = { 0 };
39+
//DMX value array and size. Entry 0 will hold startbyte, so we need 512+1 elements
40+
static uint8_t dmxData[dmxMaxChannel+1] = { 0 };
3941
static int chanSize = 0;
4042
#if !defined(DMX_SEND_ONLY)
4143
static int currentChannel = 0;
@@ -121,15 +123,17 @@ void SparkFunDMX::initWrite (int chanQuant) {
121123
#if !defined(DMX_SEND_ONLY)
122124
// Function to read DMX data
123125
uint8_t SparkFunDMX::read(int Channel) {
126+
if ((Channel > dmxMaxChannel) || (Channel < 1)) return 0; // WLEDMM prevent array out-of-bounds access
124127
if (Channel > chanSize) Channel = chanSize;
125128
return(dmxData[Channel - 1]); //subtract one to account for start byte
126129
}
127130
#endif
128131

129132
// Function to send DMX data
130133
void SparkFunDMX::write(int Channel, uint8_t value) {
131-
if (Channel < 0) Channel = 0;
132-
if (Channel > chanSize) chanSize = Channel;
134+
if (Channel < 1) Channel = 1;
135+
if (Channel+1 > chanSize) chanSize = min(dmxMaxChannel +1, Channel+1); // WLEDMM "+1" as we need to account for start byte
136+
if (Channel > dmxMaxChannel) Channel = dmxMaxChannel; // WLEDMM prevent array out-of-bounds access
133137
dmxData[0] = 0;
134138
dmxData[Channel] = value; //add one to account for start byte
135139
}
@@ -149,7 +153,7 @@ void SparkFunDMX::update() {
149153

150154
//Send DMX data
151155
DMXSerial.begin(DMXSPEED, DMXFORMAT, rxPin, txPin);//Begin the Serial port
152-
DMXSerial.write(dmxData, chanSize);
156+
DMXSerial.write(dmxData, min(dmxMaxChannel+1, chanSize)); // send max 513 bytes = start byte + 512 channels
153157
DMXSerial.flush();
154158
DMXSerial.end();//clear our DMX array, end the Hardware Serial port
155159
}
@@ -160,9 +164,11 @@ void SparkFunDMX::update() {
160164
{
161165
while (DMXSerial.available())
162166
{
163-
dmxData[currentChannel++] = DMXSerial.read();
167+
uint8_t newdata = DMXSerial.read();
168+
if (currentChannel <= dmxMaxChannel)
169+
dmxData[currentChannel++] = newdata;
164170
}
165-
if (currentChannel > chanSize) //Set the channel counter back to 0 if we reach the known end size of our packet
171+
if ((currentChannel > chanSize) || (currentChannel > dmxMaxChannel)) //Set the channel counter back to 0 if we reach the known end size of our packet
166172
{
167173

168174
portENTER_CRITICAL(&timerMux);

wled00/wled.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,9 @@
164164
#endif
165165

166166
#ifdef WLED_ENABLE_DMX
167-
#ifdef ESP8266
167+
#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2)
168168
#include "src/dependencies/dmx/ESPDMX.h"
169-
#else //ESP32
169+
#else //ESP32 or ESP32-S3
170170
#include "src/dependencies/dmx/SparkFunDMX.h"
171171
#endif
172172
#endif
@@ -468,9 +468,9 @@ WLED_GLOBAL bool arlsDisableGammaCorrection _INIT(true); // activate if
468468
WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to force max brightness if source has very dark colors that would be black
469469

470470
#ifdef WLED_ENABLE_DMX
471-
#ifdef ESP8266
471+
#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2)
472472
WLED_GLOBAL DMXESPSerial dmx;
473-
#else //ESP32
473+
#else //ESP32 or ESP32-S3
474474
WLED_GLOBAL SparkFunDMX dmx;
475475
#endif
476476
WLED_GLOBAL uint16_t e131ProxyUniverse _INIT(0); // output this E1.31 (sACN) / ArtNet universe via MAX485 (0 = disabled)

0 commit comments

Comments
 (0)