"set af nan" is accepted and stores a NaN in airtime_factor, the duty cycle
budget the roles hand to their airtime accounting. strtof() consumes the
token, so the parse guard does not fire, and no ordered comparison is true for
a NaN, so "af < 0 || af > 9" cannot reject it. "set dutycycle" writes the same
field and has the same hole.
Both commands now check the text before it is parsed: after optional white
space and sign, a number has to start with a digit or a '.'. That refuses
"nan", "inf" and their variants, and keeps every spelling that was accepted
before (signs, leading white space, ".5"). The ranges and both reply strings
are unchanged.
The check is on the text rather than on the parsed float on purpose. nRF52
builds use -Ofast, and under -ffast-math the compiler may assume a float is
never NaN or infinite. A test on the value, even one that reads its bits, can
then be folded away: clang does exactly that with a bit test at -Ofast, while
arm-none-eabi-gcc keeps it. A character test does not depend on that.
CMD_SEND_CHANNEL_TXT_MSG reads txt_type, channel_idx and a 4 byte timestamp, so
the frame needs 7 bytes before the text starts, and the branch had no length
guard. For a shorter frame "len - i" is computed in size_t, wraps, and reaches
sendGroupMessage() as a negative int. The clamp there tests
"text_len + prefix_len > MAX_TEXT_LEN", which a negative value passes, and the
following memcpy() converts the length back to a size_t: a 3 byte frame asks for
4294967292 bytes into a 197 byte stack buffer.
Two guards, because there are two mistakes. The branch now states its minimum
like most other branches of handleCmdFrame do, so a frame below 7 bytes is
answered through the existing path instead of being parsed. And
sendGroupMessage() refuses a negative length the way sendGroupData() in the same
file already does, which protects every other caller.
A frame of exactly 7 bytes keeps working and sends an empty message, as before.
Evidence. On a T-Echo running dev 428a95c6, built with
FIRMWARE_BUILD_DATE "f1-dev" and confirmed by "ver => v1.18.0 (Build: f1-dev)":
CH_TXT len=7 -> RESP_CODE_OK
GET_STATS core -> uptime=78s
CH_TXT len=3 -> NO REPLY
DEVICE_QUERY -> NO REPLY (three times over 8 s, node never came back)
'get tz.offset' printed one decimal, so a UTC+5:45 offset (5.75)
read back as 5.8. Print two decimals when the offset is on a quarter
hour (x.25 / x.75); everything else keeps one decimal.
- Clip requested power to the active PA's range instead of failing. A
stored 22 dBm was rejected at 2.4 GHz (HF PA max 13 dBm), and since
setTxPower ignores errors the sub-GHz PA stayed configured.
- Re-apply the requested power after every successful retune: PA choice
depends on the band, and set radio / tempradio only call setParams.
ESP32-S3FH4R2 (4MB flash, 2MB PSRAM, native USB-CDC) with an LR1121.
Pins, the DIO5/DIO6 RF switch table and the 1.8 V TCXO follow the HF
schematic and Waveshare's examples. Envs: repeater, room server,
companion USB/BLE and KISS modem, all on min_spiffs so roles share one
partition layout.
Only RFO_HP_LF is wired (R4 on RFO_LP_LF is not fitted), so the new
opt-in LR1121_FORCE_HP_PA flag keeps RadioLib on the HP PA at <= 14 dBm,
where it would otherwise select the unconnected LP PA.