Skip to content

Commit f4e0771

Browse files
committed
fix(cli): parse tempradio args without mutable copy and document timeout cap
1 parent cdd3d5f commit f4e0771

2 files changed

Lines changed: 63 additions & 10 deletions

File tree

docs/cli_commands.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@
211211
- `bw`: Bandwidth in kHz (7.8-500)
212212
- `sf`: Spreading factor (5-12)
213213
- `cr`: Coding rate (5-8)
214-
- `timeout_mins`: Duration in minutes (must be > 0)
214+
- `timeout_mins`: Duration in minutes (must be 1-32767)
215215

216216
**Note:** This is not saved to preferences and will clear on reboot
217217

src/helpers/CommonCLI.cpp

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "TxtDataHelpers.h"
44
#include "AdvertDataHelpers.h"
55
#include <RTClib.h>
6+
#include <stdlib.h>
67

78
// Believe it or not, this std C function is busted on some platforms!
89
static uint32_t _atoi(const char* sp) {
@@ -22,6 +23,58 @@ static bool isValidName(const char *n) {
2223
return true;
2324
}
2425

26+
static bool parseTempradioFloatField(const char*& sp, float& out_val, bool is_last = false) {
27+
while (*sp == ' ' || *sp == '\t') sp++;
28+
if (*sp == 0) return false;
29+
30+
char* ep = nullptr;
31+
out_val = strtof(sp, &ep);
32+
if (ep == sp) return false;
33+
34+
sp = ep;
35+
while (*sp == ' ' || *sp == '\t') sp++;
36+
if (is_last) return *sp == 0;
37+
if (*sp != ',') return false;
38+
sp++;
39+
return true;
40+
}
41+
42+
static bool parseTempradioIntField(const char*& sp, long& out_val, bool is_last = false) {
43+
while (*sp == ' ' || *sp == '\t') sp++;
44+
if (*sp == 0) return false;
45+
46+
char* ep = nullptr;
47+
out_val = strtol(sp, &ep, 10);
48+
if (ep == sp) return false;
49+
50+
sp = ep;
51+
while (*sp == ' ' || *sp == '\t') sp++;
52+
if (is_last) return *sp == 0;
53+
if (*sp != ',') return false;
54+
sp++;
55+
return true;
56+
}
57+
58+
static bool parseTempradioArgs(const char* args, float& freq, float& bw, uint8_t& sf, uint8_t& cr, int& timeout_mins) {
59+
long sf_l = 0;
60+
long cr_l = 0;
61+
long timeout_l = 0;
62+
const char* sp = args;
63+
64+
if (!parseTempradioFloatField(sp, freq)) return false;
65+
if (!parseTempradioFloatField(sp, bw)) return false;
66+
if (!parseTempradioIntField(sp, sf_l)) return false;
67+
if (!parseTempradioIntField(sp, cr_l)) return false;
68+
if (!parseTempradioIntField(sp, timeout_l, true)) return false;
69+
if (sf_l < 0 || sf_l > 255 || cr_l < 0 || cr_l > 255) return false;
70+
if (timeout_l < -32768 || timeout_l > 32767) return false;
71+
72+
sf = (uint8_t)sf_l;
73+
cr = (uint8_t)cr_l;
74+
timeout_mins = (int)timeout_l;
75+
return true;
76+
}
77+
2578
void CommonCLI::loadPrefs(FILESYSTEM* fs) {
2679
if (fs->exists("/com_prefs")) {
2780
loadPrefsInt(fs, "/com_prefs"); // new filename
@@ -250,15 +303,15 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
250303
strcpy(reply, "ERR: bad pubkey");
251304
}
252305
} else if (memcmp(command, "tempradio ", 10) == 0) {
253-
strcpy(tmp, &command[10]);
254-
const char *parts[5];
255-
int num = mesh::Utils::parseTextParts(tmp, parts, 5);
256-
float freq = num > 0 ? strtof(parts[0], nullptr) : 0.0f;
257-
float bw = num > 1 ? strtof(parts[1], nullptr) : 0.0f;
258-
uint8_t sf = num > 2 ? atoi(parts[2]) : 0;
259-
uint8_t cr = num > 3 ? atoi(parts[3]) : 0;
260-
int temp_timeout_mins = num > 4 ? atoi(parts[4]) : 0;
261-
if (freq >= 300.0f && freq <= 2500.0f && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7.0f && bw <= 500.0f && temp_timeout_mins > 0) {
306+
float freq = 0.0f;
307+
float bw = 0.0f;
308+
uint8_t sf = 0;
309+
uint8_t cr = 0;
310+
int temp_timeout_mins = 0;
311+
bool parsed = parseTempradioArgs(&command[10], freq, bw, sf, cr, temp_timeout_mins);
312+
313+
if (parsed && freq >= 300.0f && freq <= 2500.0f && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 &&
314+
bw >= 7.0f && bw <= 500.0f && temp_timeout_mins > 0) {
262315
_callbacks->applyTempRadioParams(freq, bw, sf, cr, temp_timeout_mins);
263316
sprintf(reply, "OK - temp params for %d mins", temp_timeout_mins);
264317
} else {

0 commit comments

Comments
 (0)