From 5d48ad0bfe17d54997fd6d8d3353ceee10d53cb6 Mon Sep 17 00:00:00 2001 From: Seth Freiberg Date: Sun, 14 Jun 2026 16:29:10 -0400 Subject: [PATCH] fix: harden endpoints against malformed input (final-review findings) - /api/repeaters: bad ?limit= falls back to 25 instead of crashing the handler - repeaters.load(): tolerate a corrupted repeaters.json (JSONDecodeError -> []) - tune_repeater/do_POST: catch TypeError so a null field yields {ok:false} not a reset --- radio.py | 2 +- repeaters.py | 2 +- server.py | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/radio.py b/radio.py index ad4bcdf..e47eab3 100644 --- a/radio.py +++ b/radio.py @@ -196,7 +196,7 @@ class Radio: def attempt(name, fn): try: fn(); steps[name] = True - except (CIVError, ValueError, OSError) as e: + except (CIVError, ValueError, TypeError, OSError) as e: steps[name] = False; errors[name] = str(e) attempt("freq", lambda: self.set_frequency(int(round(rec["output_mhz"] * 1e6)))) diff --git a/repeaters.py b/repeaters.py index 5bc2c39..3b880d6 100644 --- a/repeaters.py +++ b/repeaters.py @@ -72,7 +72,7 @@ def load(path): try: with open(path) as f: data = json.load(f) - except FileNotFoundError: + except (FileNotFoundError, json.JSONDecodeError): return [] return data if isinstance(data, list) else data.get("repeaters", []) diff --git a/server.py b/server.py index 8eabbd9..bec08ee 100644 --- a/server.py +++ b/server.py @@ -90,7 +90,10 @@ class Handler(BaseHTTPRequestHandler): from urllib.parse import urlparse, parse_qs qs = parse_qs(urlparse(self.path).query) q = qs.get("q", [""])[0] - limit = int(qs.get("limit", ["25"])[0]) + try: + limit = int(qs.get("limit", ["25"])[0]) + except ValueError: + limit = 25 recs = repeaters.search(repeaters.load(REPEATERS_JSON), q, limit) self._json({"ok": True, "repeaters": recs}) else: @@ -101,7 +104,7 @@ class Handler(BaseHTTPRequestHandler): try: body = json.loads(self.rfile.read(length) or b"{}") self._json(apply_control(self.path, body)) - except (CIVError, OSError, ValueError, KeyError) as e: + except (CIVError, OSError, ValueError, TypeError, KeyError) as e: self._json({"ok": False, "error": str(e)}, 200)