Skip to content

Commit d8b66da

Browse files
committed
Prevent OOB POWER_VALUES array access if array doesn't have enough values
1 parent bbfa686 commit d8b66da

File tree

2 files changed

+14
-17
lines changed

2 files changed

+14
-17
lines changed

src/include/target/Unified_ESP32_TX.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#define POWER_OUTPUT_VALUES hardware_i16_array(HARDWARE_power_values)
4747
#define POWER_OUTPUT_VALUES_COUNT hardware_int(HARDWARE_power_values_count)
4848
#define POWER_OUTPUT_VALUES2 hardware_i16_array(HARDWARE_power_values2)
49+
#define POWER_OUTPUT_VALUES2_COUNT POWER_OUTPUT_VALUES_COUNT
4950
#define POWER_OUTPUT_VALUES_DUAL hardware_i16_array(HARDWARE_power_values_dual)
5051
#define POWER_OUTPUT_VALUES_DUAL_COUNT hardware_int(HARDWARE_power_values_dual_count)
5152

src/lib/POWERMGNT/POWERMGNT.cpp

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ PowerLevels_e PowerLevelContainer::CurrentPower = PWR_COUNT; // default "undefin
7878
PowerLevels_e POWERMGNT::FanEnableThreshold = PWR_250mW;
7979
int8_t POWERMGNT::CurrentSX1280Power = 0;
8080

81-
static const int16_t *powerValues;
82-
static const int16_t *powerValuesDual;
8381
extern bool isUsingPrimaryFreqBand();
8482

8583
static int8_t powerCaliValues[PWR_COUNT] = {0};
@@ -88,6 +86,11 @@ static int8_t powerCaliValues[PWR_COUNT] = {0};
8886
nvs_handle POWERMGNT::handle = 0;
8987
#endif
9088

89+
// Get the POWER_VALUE_X to send to DAC/RF chip of the speficied index into the array
90+
// If the index is higher than the array has values, return the LOWEST power value
91+
// Maybe the user will realize they can't just set MaxPower to 2000mW and get more power
92+
#define SAFE_GET_POWER_VALUE(values, idx) (((idx) < (values##_COUNT)) ? (values)[idx] : (values)[0])
93+
9194
PowerLevels_e POWERMGNT::incPower()
9295
{
9396
if (CurrentPower < getMaxPower())
@@ -109,7 +112,7 @@ PowerLevels_e POWERMGNT::decPower()
109112
void POWERMGNT::incSX1280Output()
110113
{
111114
// Power adjustment is capped to within +-3dB of the target power level to prevent power run-away
112-
if (CurrentSX1280Power < 13 && CurrentSX1280Power < powerValues[CurrentPower] + 3)
115+
if (CurrentSX1280Power < 13 && CurrentSX1280Power < SAFE_GET_POWER_VALUE(POWER_OUTPUT_VALUES, CurrentPower) + 3)
113116
{
114117
CurrentSX1280Power++;
115118
Radio.SetOutputPower(CurrentSX1280Power);
@@ -119,7 +122,7 @@ void POWERMGNT::incSX1280Output()
119122
void POWERMGNT::decSX1280Output()
120123
{
121124
// Power adjustment is capped to within +-3dB of the target power level to prevent power run-away
122-
if (CurrentSX1280Power > -18 && CurrentSX1280Power > powerValues[CurrentPower] - 3)
125+
if (CurrentSX1280Power > -18 && CurrentSX1280Power > SAFE_GET_POWER_VALUE(POWER_OUTPUT_VALUES, CurrentPower) - 3)
123126
{
124127
CurrentSX1280Power--;
125128
Radio.SetOutputPower(CurrentSX1280Power);
@@ -214,11 +217,6 @@ void POWERMGNT::init()
214217
{
215218
PowerLevelContainer::CurrentPower = PWR_COUNT;
216219

217-
powerValues = POWER_OUTPUT_VALUES;
218-
if (POWER_OUTPUT_VALUES_DUAL != nullptr)
219-
{
220-
powerValuesDual = POWER_OUTPUT_VALUES_DUAL;
221-
}
222220
LoadCalibration();
223221
setDefaultPower();
224222
}
@@ -244,43 +242,41 @@ void POWERMGNT::setDefaultPower()
244242
void POWERMGNT::setPower(PowerLevels_e Power)
245243
{
246244
Power = constrain(Power, getMinPower(), getMaxPower());
247-
PowerLevels_e PowerDual = Power;
248-
249245
if (Power == CurrentPower)
250246
return;
251-
252247
CurrentPower = Power;
253248

254249
// When using SubHGz with CE, limit to a max of 25mW.
255250
#if defined(Regulatory_Domain_EU_CE_2400) && defined(RADIO_LR1121)
256251
if (Power > PWR_25mW && isUsingPrimaryFreqBand())
257252
{
258-
Power = (MinPower > PWR_25mW) ? MinPower : PWR_25mW;
253+
Power = (MinPower > PWR_25mW) ? getMinPower() : PWR_25mW;
259254
}
260255
#endif
261256

257+
const uint8_t powerIdx = Power - getMinPower();
262258
if (POWER_OUTPUT_DACWRITE)
263259
{
264260
if (POWER_OUTPUT_VALUES2 != nullptr)
265261
{
266-
Radio.SetOutputPower(POWER_OUTPUT_VALUES2[Power - MinPower]);
262+
Radio.SetOutputPower(SAFE_GET_POWER_VALUE(POWER_OUTPUT_VALUES2, powerIdx));
267263
}
268264
#if defined(PLATFORM_ESP32_S3) || defined(PLATFORM_ESP32_C3) || defined(PLATFORM_ESP8266)
269265
ERRLN("ESP32-S3/C3 and ESP8285 MCUs do not have a DAC");
270266
#else
271-
dacWrite(GPIO_PIN_RFamp_APC2, powerValues[Power - MinPower]);
267+
dacWrite(GPIO_PIN_RFamp_APC2, SAFE_GET_POWER_VALUE(POWER_OUTPUT_VALUES, powerIdx));
272268
#endif
273269
}
274270
else
275271
{
276-
CurrentSX1280Power = powerValues[Power - MinPower] + powerCaliValues[Power];
272+
CurrentSX1280Power = SAFE_GET_POWER_VALUE(POWER_OUTPUT_VALUES, powerIdx) + powerCaliValues[Power];
277273
Radio.SetOutputPower(CurrentSX1280Power);
278274
}
279275

280276
#if defined(RADIO_LR1121)
281277
if (POWER_OUTPUT_VALUES_DUAL != nullptr)
282278
{
283-
Radio.SetOutputPower(powerValuesDual[PowerDual - MinPower], false); // Set the high frequency power setting.
279+
Radio.SetOutputPower(SAFE_GET_POWER_VALUE(POWER_OUTPUT_VALUES_DUAL, powerIdx), false); // Set the high frequency power setting.
284280
}
285281
#endif
286282

0 commit comments

Comments
 (0)