Skip to content

Commit c1394cd

Browse files
authored
Fix missing index check for Tokenizer_GetArg functions (#2058)
* Fix missing "safeguard" for invalid iargument index for Tokenizer_GetArgIntegerRange() need to agree an return value in this cas. I choosed range_Min Tokenizer_GetArgInteger() Tokenizer_GetArgFloat() Added check for negative index to all TokenizerGetXX functions Added selftest for these cases to selftest_tokenizer.c Tried to fix selftest_tasmota.c - it relayed on the previous behavior to return a value from a prevoius "TokenizeString()" call Examlpe of what was changed: - SIM_SendFakeMQTTAndRunSimFrame_CMND("CT", ""); + SIM_SendFakeMQTTAndRunSimFrame_CMND("CT", "153"); (later 153 is used for "assert" in SELFTEST_ASSERT_JSON_VALUE_INTEGER(0, "CT", 153); ) * revert modifications to tasmota selftests. Safeguarding command in src/cmnds/cmd_newLEDDriver.c (reject calls with insufficient number of arguments) Make "0" default "addMode" for "add_dimmer()" * Add some more checks. Hopefully it's complete now
1 parent efd383a commit c1394cd

4 files changed

Lines changed: 71 additions & 10 deletions

File tree

src/cmnds/cmd_newLEDDriver.c

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -912,15 +912,17 @@ static commandResult_t temperature(const void *context, const char *cmd, const c
912912
int tmp;
913913
//if (!wal_strnicmp(cmd, "POWERALL", 8)){
914914

915-
ADDLOG_DEBUG(LOG_FEATURE_CMD, " temperature (%s) received with args %s",cmd,args);
916-
917-
Tokenizer_TokenizeString(args, 0);
915+
Tokenizer_TokenizeString(args, 0);
918916

919-
tmp = Tokenizer_GetArgInteger(0);
917+
ADDLOG_DEBUG(LOG_FEATURE_CMD, " temperature (%s) received with args %s",cmd,args);
918+
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
919+
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
920+
}
920921

921-
LED_SetTemperature(tmp, 1);
922922

923-
return CMD_RES_OK;
923+
tmp = Tokenizer_GetArgInteger(0);
924+
LED_SetTemperature(tmp, 1);
925+
return CMD_RES_OK;
924926
//}
925927
//return 0;
926928
}
@@ -994,6 +996,9 @@ static commandResult_t enableAll(const void *context, const char *cmd, const cha
994996
ADDLOG_DEBUG(LOG_FEATURE_CMD, " enableAll (%s) received with args %s",cmd,args);
995997

996998
Tokenizer_TokenizeString(args, 0);
999+
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
1000+
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
1001+
}
9971002

9981003
a = Tokenizer_GetArg(0);
9991004
if (a && !stricmp(a, "toggle")) {
@@ -1178,6 +1183,9 @@ static commandResult_t add_temperature(const void *context, const char *cmd, con
11781183
int bWrapAroundInsteadOfHold;
11791184

11801185
Tokenizer_TokenizeString(args, 0);
1186+
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 2)) {
1187+
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
1188+
}
11811189

11821190
iVal = Tokenizer_GetArgInteger(0);
11831191
bWrapAroundInsteadOfHold = Tokenizer_GetArgInteger(1);
@@ -1191,9 +1199,12 @@ static commandResult_t add_dimmer(const void *context, const char *cmd, const ch
11911199
int addMode;
11921200

11931201
Tokenizer_TokenizeString(args, 0);
1202+
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
1203+
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
1204+
}
11941205

11951206
iVal = Tokenizer_GetArgInteger(0);
1196-
addMode = Tokenizer_GetArgInteger(1);
1207+
addMode = Tokenizer_GetArgIntegerDefault(1,0);
11971208

11981209
LED_AddDimmer(iVal, addMode, 0);
11991210

@@ -1204,6 +1215,9 @@ static commandResult_t dimmer(const void *context, const char *cmd, const char *
12041215
int iVal = 0;
12051216

12061217
ADDLOG_DEBUG(LOG_FEATURE_CMD, " dimmer (%s) received with args %s",cmd,args);
1218+
if (!args || args[0] == '\0') {
1219+
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
1220+
}
12071221

12081222
// according to Elektroda.com users, domoticz sends following string:
12091223
// {"brightness":52,"state":"ON"}
@@ -1383,6 +1397,9 @@ commandResult_t LED_SetBaseColor_HSB(const void *context, const char *cmd, const
13831397
const char *p;
13841398

13851399
Tokenizer_TokenizeString(args, 0);
1400+
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) { // especially important here: if ArgsCount is 0, it would proceed to els, fetching 3 invalid values!!
1401+
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
1402+
}
13861403
if (Tokenizer_GetArgsCount() == 1) {
13871404
p = args;
13881405
hue = atoi(p);
@@ -1583,6 +1600,9 @@ static commandResult_t lerpSpeed(const void *context, const char *cmd, const cha
15831600
static commandResult_t cmdDimmerScale(const void *context, const char *cmd, const char *args, int cmdFlags) {
15841601
// Use tokenizer, so we can use variables (eg. $CH11 as variable)
15851602
Tokenizer_TokenizeString(args, 0);
1603+
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
1604+
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
1605+
}
15861606

15871607
g_brightnessScale = Tokenizer_GetArgFloat(0);
15881608

@@ -1672,6 +1692,9 @@ static commandResult_t setSaturation(const void *context, const char *cmd, const
16721692

16731693
// Use tokenizer, so we can use variables (eg. $CH11 as variable)
16741694
Tokenizer_TokenizeString(args, 0);
1695+
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
1696+
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
1697+
}
16751698

16761699
f = Tokenizer_GetArgFloat(0);
16771700

@@ -1692,6 +1715,9 @@ static commandResult_t setHue(const void *context, const char *cmd, const char *
16921715

16931716
// Use tokenizer, so we can use variables (eg. $CH11 as variable)
16941717
Tokenizer_TokenizeString(args, 0);
1718+
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
1719+
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
1720+
}
16951721

16961722
f = Tokenizer_GetArgFloat(0);
16971723

src/cmnds/cmd_tokenizer.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ const char *Tokenizer_GetArgExpanding(int i) {
144144
const char *Tokenizer_GetArg(int i) {
145145
const char *s;
146146

147-
if (i >= g_numArgs)
147+
if (i < 0 || g_numArgs <= i) {
148148
return 0;
149+
}
149150

150151
if (g_argsExpanded[i][0] != 0) {
151152
return g_argsExpanded[i];
@@ -200,6 +201,15 @@ const char *Tokenizer_GetArgFrom(int i) {
200201
}
201202
int Tokenizer_GetArgIntegerRange(int i, int rangeMin, int rangeMax) {
202203
int ret = Tokenizer_GetArgInteger(i);
204+
205+
//
206+
// to be discussed: What to return in case of an invalid index? min or max or ???
207+
//
208+
if (i < 0 || g_numArgs <= i) {
209+
ADDLOG_ERROR(LOG_FEATURE_CMD, "Invalid argument index %i! Using minumum value %i!",i,rangeMin);
210+
return rangeMin;
211+
}
212+
203213
if(ret < rangeMin) {
204214
ret = rangeMin;
205215
ADDLOG_ERROR(LOG_FEATURE_CMD, "Argument %i (val=%i) was out of range [%i,%i], clamped",i,ret,rangeMax,rangeMin);
@@ -227,7 +237,7 @@ int Tokenizer_GetPin(int i, int def) {
227237
int Tokenizer_GetArgIntegerDefault(int i, int def) {
228238
int r;
229239

230-
if (g_numArgs <= i) {
240+
if (i < 0 || g_numArgs <= i) {
231241
return def;
232242
}
233243
r = Tokenizer_GetArgInteger(i);
@@ -237,7 +247,7 @@ int Tokenizer_GetArgIntegerDefault(int i, int def) {
237247
float Tokenizer_GetArgFloatDefault(int i, float def) {
238248
float r;
239249

240-
if (g_numArgs <= i) {
250+
if (i < 0 || g_numArgs <= i) {
241251
return def;
242252
}
243253
r = Tokenizer_GetArgFloat(i);
@@ -247,6 +257,9 @@ float Tokenizer_GetArgFloatDefault(int i, float def) {
247257
int Tokenizer_GetArgInteger(int i) {
248258
const char *s;
249259
int ret;
260+
if (i < 0 || g_numArgs <= i) {
261+
return 0;
262+
}
250263

251264
s = g_args[i];
252265
if (s == 0)
@@ -278,6 +291,9 @@ int Tokenizer_GetArgInteger(int i) {
278291
return atoi(s);
279292
}
280293
float Tokenizer_GetArgFloat(int i) {
294+
if (i < 0 || g_numArgs <= i) {
295+
return 0.0f;
296+
}
281297
#if !ENABLE_EXPAND_CONSTANT
282298
int channelIndex;
283299
#endif

src/selftest/selftest_local.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ void SelfTest_Failed(const char *file, const char *function, int line, const cha
2828
#define SELFTEST_ASSERT_PIN_BOOLEAN(pinIndex, res) SELFTEST_ASSERT((SIM_GetSimulatedPinValue(pinIndex) == res));
2929
#define SELFTEST_ASSERT_ARGUMENT(argumentIndex, res) SELFTEST_ASSERT(!strcmp(Tokenizer_GetArg(argumentIndex), res));
3030
#define SELFTEST_ASSERT_ARGUMENT_INTEGER(argumentIndex, res) SELFTEST_ASSERT((Tokenizer_GetArgInteger(argumentIndex) == res));
31+
#define SELFTEST_ASSERT_ARGUMENT_FLOAT(argumentIndex, res) SELFTEST_ASSERT((Tokenizer_GetArgFloat(argumentIndex) == res));
3132
#define SELFTEST_ASSERT_ARGUMENTS_COUNT(wantedCount) SELFTEST_ASSERT((Tokenizer_GetArgsCount() == wantedCount));
3233
#define SELFTEST_ASSERT_JSON_VALUE_STRING(obj, varName, res) SELFTEST_ASSERT(!strcmp(Test_GetJSONValue_String(varName, obj), res));
3334
#define SELFTEST_ASSERT_JSON_ONE_OF_TWO_VALUES_STRING(obj, varName, res, res2) SELFTEST_ASSERT(!strcmp(Test_GetJSONValue_String(varName, obj), res) || !strcmp(Test_GetJSONValue_String(varName, obj), res2));

src/selftest/selftest_tokenizer.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,24 @@ void Test_Tokenizer() {
135135
SELFTEST_ASSERT_ARGUMENT(2, "level=77");
136136
SELFTEST_ASSERT_ARGUMENT(3, "0");
137137
SELFTEST_ASSERT_STRING(Tokenizer_GetArgFrom(2), "level=$CH5 $CH6")
138+
139+
// test for invalid responses
140+
Tokenizer_TokenizeString("1 2 3 4 5 6.6 7.7", 0);
141+
SELFTEST_ASSERT_ARGUMENTS_COUNT(7);
142+
SELFTEST_ASSERT_ARGUMENT_INTEGER(0, 1);
143+
SELFTEST_ASSERT_ARGUMENT_INTEGER(-1, 0); // negative index: default 0
144+
SELFTEST_ASSERT_ARGUMENT_INTEGER(7, 0); // invalid index: default 0
145+
SELFTEST_ASSERT_ARGUMENT_INTEGER(1024, 0); // invalid index: default 0
146+
SELFTEST_ASSERT_ARGUMENT_INTEGER(1, 2);
147+
SELFTEST_ASSERT_ARGUMENT_INTEGER(2, 3);
148+
SELFTEST_ASSERT_ARGUMENT_INTEGER(3, 4);
149+
SELFTEST_ASSERT_ARGUMENT_INTEGER(4, 5);
150+
SELFTEST_ASSERT_ARGUMENT_FLOAT(5, 6.6f);
151+
SELFTEST_ASSERT_ARGUMENT_FLOAT(6, 7.7f);
152+
SELFTEST_ASSERT_ARGUMENT_FLOAT(-1, 0.0f); // negative index: default 0.0
153+
SELFTEST_ASSERT_ARGUMENT_FLOAT(7, 0.0f); // invalid index: default 0.0
154+
SELFTEST_ASSERT_ARGUMENT_FLOAT(1024, 0.0f); // invalid index: default 0.0
155+
138156
}
139157

140158
#endif

0 commit comments

Comments
 (0)