From 4ff81dd03aef3aa5969b42e6257c2a63ea502683 Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Wed, 22 Jul 2026 02:49:05 +0200 Subject: [PATCH] Harden FS20/FHT and disable it by default Command codes 0x1c-0x1f are documented as unused ("frei") and never sent by real devices, so accepting them only widened the false-decode surface for foreign bitstreams that happen to pass parity and the checksum band. --- README.md | 2 +- conf/rtl_433.example.conf | 2 +- src/devices/fs20.c | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 08dc5cac..15da72eb 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md). [119] Bresser Weather Center 5-in-1 [120] Digitech XC-0324 / AmbientWeather FT005TH temp/hum sensor [121] Opus/Imagintronix XT300 Soil Moisture - [122] FS20 / FHT + [122]* FS20 / FHT [123]* Jansite TPMS Model TY02S [124] LaCrosse/ELV/Conrad WS7000/WS2500 weather sensors [125] TS-FT002 Wireless Ultrasonic Tank Liquid Level Meter With Temperature Sensor diff --git a/conf/rtl_433.example.conf b/conf/rtl_433.example.conf index 224593ee..1adbe5dd 100644 --- a/conf/rtl_433.example.conf +++ b/conf/rtl_433.example.conf @@ -361,7 +361,7 @@ convert si protocol 119 # Bresser Weather Center 5-in-1 protocol 120 # Digitech XC-0324 / AmbientWeather FT005TH temp/hum sensor protocol 121 # Opus/Imagintronix XT300 Soil Moisture - protocol 122 # FS20 / FHT +# protocol 122 # FS20 / FHT # protocol 123 # Jansite TPMS Model TY02S protocol 124 # LaCrosse/ELV/Conrad WS7000/WS2500 weather sensors protocol 125 # TS-FT002 Wireless Ultrasonic Tank Liquid Level Meter With Temperature Sensor diff --git a/src/devices/fs20.c b/src/devices/fs20.c index 53671971..00c41b03 100644 --- a/src/devices/fs20.c +++ b/src/devices/fs20.c @@ -20,6 +20,8 @@ enum { FS20_BASE_FRAME_BITS = FS20_BASE_BYTES * FS20_PARITY_BYTE_BITS, FS20_EXT_FRAME_BITS = FS20_EXT_BYTES * FS20_PARITY_BYTE_BITS, FS20_EXT_FLAG = 0x20, + FS20_CMD_MASK = 0x1f, + FS20_CMD_RESERVED_MIN = 0x1c, // 0x1c-0x1f ("frei"/unused) never sent by real devices FHT_CMD_MASK = 0x0f, FHT_CMD_END_OF_SYNC = 0x00, }; @@ -277,6 +279,12 @@ static int fs20_decode(r_device *decoder, bitbuffer_t *bitbuffer) return DECODE_FAIL_SANITY; } + // FS20 command codes 0x1c-0x1f are documented as unused/reserved and + // never sent by real devices; a foreign bitstream is the likelier source. + if (is_fs20 && (cmd & FS20_CMD_MASK) >= FS20_CMD_RESERVED_MIN) { + return DECODE_FAIL_SANITY; + } + // A real FS20 housecode is a user-set DIP-switch code, effectively // uniform over the whole address space; an all-zero housecode and // address is a degenerate pattern that mainly shows up when foreign @@ -334,4 +342,5 @@ r_device const fs20 = { .reset_limit = 9000, .decode_fn = &fs20_decode, .fields = output_fields, + .disabled = 1, // false decodes from foreign bitstreams, see issue #3611 };