Skip to content

Commit e7f07f5

Browse files
committed
pinmanager robustness improvement
make sure that array bounds are not violated in pinManager class.
1 parent da7972c commit e7f07f5

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

wled00/pin_manager.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,9 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
107107
}
108108
if (!isPinOk(gpio, mptArray[i].isOutput)) {
109109
#ifdef WLED_DEBUG
110-
DEBUG_PRINT(F("PIN ALLOC: Invalid pin attempted to be allocated: "));
110+
DEBUG_PRINT(F("PIN ALLOC: Invalid pin attempted to be allocated: GPIO "));
111111
DEBUG_PRINT(gpio);
112+
DEBUG_PRINT(" as "); DEBUG_PRINT(mptArray[i].isOutput ? "output": "input");
112113
DEBUG_PRINTLN(F(""));
113114
#endif
114115
shouldFail = true;
@@ -142,6 +143,9 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
142143
// as this can greatly simplify configuration arrays
143144
continue;
144145
}
146+
if (gpio >= WLED_NUM_PINS)
147+
continue; // other unexpected GPIO => avoid array bounds violation
148+
145149
byte by = gpio >> 3;
146150
byte bi = gpio - 8*by;
147151
bitWrite(pinAlloc[by], bi, true);
@@ -160,7 +164,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
160164
bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
161165
{
162166
// HW I2C & SPI pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair
163-
if (!isPinOk(gpio, output) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) {
167+
if (!isPinOk(gpio, output) || (gpio >= WLED_NUM_PINS) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) {
164168
#ifdef WLED_DEBUG
165169
if (gpio < 255) { // 255 (-1) is the "not defined GPIO"
166170
if (!isPinOk(gpio, output)) {
@@ -209,6 +213,7 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag)
209213
{
210214
if (!isPinOk(gpio, false)) return true;
211215
if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) return false;
216+
if (gpio >= WLED_NUM_PINS) return false; // catch error case, to avoid array out-of-bounds access
212217
byte by = gpio >> 3;
213218
byte bi = gpio - (by<<3);
214219
return bitRead(pinAlloc[by], bi);
@@ -265,6 +270,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
265270
}
266271

267272
PinOwner PinManagerClass::getPinOwner(byte gpio) {
273+
if (gpio >= WLED_NUM_PINS) return PinOwner::None; // catch error case, to avoid array out-of-bounds access
268274
if (!isPinOk(gpio, false)) return PinOwner::None;
269275
return ownerTag[gpio];
270276
}

wled00/pin_manager.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,14 @@ static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must b
6666
class PinManagerClass {
6767
private:
6868
#ifdef ESP8266
69+
#define WLED_NUM_PINS 17
6970
uint8_t pinAlloc[3] = {0x00, 0x00, 0x00}; //24bit, 1 bit per pin, we use first 17bits
70-
PinOwner ownerTag[17] = { PinOwner::None };
71+
PinOwner ownerTag[WLED_NUM_PINS] = { PinOwner::None };
7172
#else
73+
#define WLED_NUM_PINS 50
7274
uint8_t pinAlloc[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 56bit, 1 bit per pin, we use 50 bits on ESP32-S3
7375
uint8_t ledcAlloc[2] = {0x00, 0x00}; //16 LEDC channels
74-
PinOwner ownerTag[50] = { PinOwner::None }; // new MCU's have up to 50 GPIO
76+
PinOwner ownerTag[WLED_NUM_PINS] = { PinOwner::None }; // new MCU's have up to 50 GPIO
7577
#endif
7678
struct {
7779
uint8_t i2cAllocCount : 4; // allow multiple allocation of I2C bus pins but keep track of allocations

0 commit comments

Comments
 (0)