7.4 KiB
Code-Review: Schwachstellen, Fehler, Verbesserungspotential
Stand: 2026-10-30, Version 0.7.0. Die 114 Tests und der Handbuch-Test liefen grün. „Bestätigt“ heißt: nachgestellt. Alles andere stammt aus dem Lesen des Codes.
Schwachstellen (alle vier behoben, siehe CHANGELOG)
- Befehlseinschleusung über Tabellendaten in
report(bestätigt). lib/rdb/cmd/report.rb:11-12: Bei<!cmd <Spalte>!>werden Zellwerte ungefiltert in einen Backtick-Aufruf eingesetzt. Eine Zelle mittouch PWNEDhat die Datei angelegt. Abhilfe:Shellwords.escape, oder in der Doku als „nur vertrauenswürdige Daten“ kennzeichnen. Behoben: Werte werden mitShellwords.escapeeingesetzt. screenerzeugt Shell-Code aus Spaltennamen (report.rb:50-70). Namen stehen unquotiert inread NAMEundecho "$NAME"; Leerzeichen,;oder$(…)brechen das Skript oder führen Code aus. Werte werden ebenfalls nicht maskiert. Behoben: Spaltennamen müssen gültige Shell-Variablennamen sein.- Lock-Dateien in
/tmp(access.rb:121). Vorhersagbare Namen, andere Benutzer können sie anlegen oder löschen.lockliest und hängt an, ohneflock(Race). Keine Prüfung, ob die PID noch lebt; nach einem Absturz bleibt das Schloss. Behoben: privates Verzeichnis/tmp/rdb-locks-<UID>(0700) undflock. Offen: verwaiste Schlösser nach Absturz (eine PID-Prüfung bricht Tests und Handbuch, die erfundene PIDs nutzen). vilocknicht atomar (access.rb:134). Race zwischenFile.exist?undrename; nachkill -9bleibtLOCK…liegen. Behoben: atomare Sperre überFile.link. Offen: nachkill -9bleibtLOCK…liegen.
Fehler (1–8 behoben, 9 teilweise)
- Umlaute in Spaltennamen (bestätigt).
to_awkerkennt nur[A-Za-z_#]und ASCII-\w.row 'Über > 3'scheitert mit awk-Fehler. Relevant für die DE/AT/CH-Tarife. - Nicht-UTF-8-Daten (bestätigt). Latin-1-Datei führt zu
invalid byte sequence in UTF-8mit Stacktrace (table.rb:28). Abhilfe: binär lesen undscrub/force_encoding, oder Kodierungsoption. - Kein Fehlerfang auf oberster Ebene (bestätigt). Stacktraces statt
Meldungen bei ungültiger Regex (
update.rdbmit/[, access.rb:277;sale, act.rb:345),Date::Errorinto_julian,Errno::*. Abhilfe:rescue StandardErrorinbin/rdb/Rdb.run. EDITORmit Argumenten (bestätigt, behoben).system(ENV['EDITOR'], datei)invilockundedit_cells(access.rb:138, access.rb:150) behandelt"nvim -f"als einen Programmnamen. Der Editor startet nie,update.rdbmeldet trotzdem „record replaced“. Abhilfe:Shellwords.split, Rückgabewert prüfen.- Datenverlust-Risiko bei
update.rdb e(access.rb:289). Der Satz wird vor dem Editieren geleert; bei Abbruch ist er weg. Erst nach erfolgreichem Editieren schreiben. - Tab/Zeilenumbruch in Werten ungeprüft (bestätigt für Tab).
append,enter,replace,veschreiben Zellen unverändert; ein Tab erzeugte eine Zeile mit 3 statt 2 Spalten (check.rdbmeldet es). - Nicht atomares Schreiben.
splice,build,substituteüberschreiben direkt, ohne temporäre Datei plusrename, ohneflock. - Inkonsistente Vergleiche bei
-mb/-mi(nur im Code gesehen). Index sortiert mitto_s, Suche vergleicht mitstrip; führende Leerzeichen und-xohne Teilsuche können falsch ausfallen. - Kleinigkeiten.
sorttable -rkehrt gleiche Schlüssel um (reverse!nach stabiler Sortierung);-nrfgilt global für alle Spalten;jointable -nwird ignoriert;total/meanlehnen1e3ab; eine Zeile aus lauter leeren Zellen gilt als gelöscht (fast.rb:21).
Stand der Behebung: 1 (Umlaute: Unicode-fähiger Umsetzer), 2 (Latin-1 wird als UTF-8
gelesen), 3 (Fehler als eine Zeile, RDB_DEBUG=1 für den Backtrace), 4 (EDITOR mit
Argumenten, Editorfehler wird gemeldet), 5 (Satz wird in jedem Fall zurückgeschrieben),
6 (Rdb.check_cells!), 7 (Rdb.write_file: temporäre Datei plus rename) und 8
(Sortierschlüssel ohne Leerzeichen) sind behoben, jeweils mit Test.
Bei 9 ist nur sorttable -r behoben. Bewusst offen: -nrf gilt global (so beschreibt es
das Handbuch), jointable -n ist unklar spezifiziert, 1e3 als Zahl und die Zeile aus
leeren Zellen als „gelöscht“ sind Eigenheiten des Formats. Bei 8 bleibt -x (Faltung) beim
Index ohne Entsprechung in der Suche offen.
Verbesserungspotential
- Indexe sind nicht schnell. — Behoben (Seek statt Volllesen, lazy
Data). Ursprünglich: Jede Suche liest Tabelle und Indexdatei komplett (fast.rb:151, fast.rb:171,Data.newpro Schlüssel indelete/update.rdb): O(n) pro Schlüssel. Abhilfe: mitseek/preaddirekt an der Fixbreiten-Position lesen. - Schlechte Hash-Funktion — Behoben (FNV-1a, größter Eimer 4). Ursprünglich: (fast.rb:68):
bytes.sum % slots. Bestätigt: 3000 fünfstellige Nummern landen in 30 Slots, größter Bucket 223. Abhilfe: FNV-1a o. Ä., Primzahl-Slotzahl. - Geld in
Float— Behoben (Rationalintotal/mean/subtotalund /act). Ursprünglich: (act.rb:11,to_fim /act-Teil und intotal). Abhilfe:BigDecimaloder ganzzahlige Rappen. - awk-Brücke — bleibt so (Entscheidung 2026-10-30).
awkundawk_textteilen sich jetzt den Aufruf. Streaming und ein eigener Ausdrucksparser wären ein Umbau mit Verhaltensrisiko (awk-Syntax ist dokumentierte Schnittstelle). Ursprünglich: (env.rb:119-138): ganze Tabelle als String durchcapture3, kein Streaming; handgeschriebener Parser erkennt Strings und Regexe heuristisch (prev) und hängt vom awk-Dialekt ab. - Globale Methoden auf
Object— Behoben (Rdb::Helpers, Konstanten inRdb). Ursprünglich: (fast_opts,lock_file,num,money,ask,need,show_record…). In ein Modul kapseln und inEnveinbinden. - Doppelter Code — Behoben (
Table.head_text,dash_cells,headed?;awküberawk_text). Ursprünglich:awk/awk_text; Schlüsseltabellen-Parsing infast_opts/key_columns; von Hand gebaute Kopf-/Strichzeilen trotzTable.dash_row. - Tests — Behoben (Suite 70 s → 21 s). Parallel, und
bin/rdbstartet mit--disable-gems(ca. 85 statt 170 ms je Befehl). Fehlerfälle haben jetzt Tests. Den Rest der Zeit brauchttest_testall_runs_demo_script(rund 300 Befehle nacheinander). Ursprünglich: Laufzeit ca. 66 s wegen eines Ruby-Prozesses pro Test. Fehlerfälle (Encoding, Tab in Wert, Locks, Editor) nicht abgedeckt; Tests direkt gegenRdb.runim Prozess wären schneller. - Repo — bleibt so (Entscheidung 2026-10-30). Ursprünglich:
demo/fact.pl,fact_lc.pl,rule.plsind ungetrackt;demo/testall.old(1187 Zeilen) wäre als Golden-File-Test besser gepflegt.
Empfohlene Reihenfolge
Schwachstellen, Fehler und Verbesserungen 1–3 und 5–7 sind erledigt. Die awk-Brücke (4) und das Repo (8) bleiben auf Entscheidung des Autors so. Das Review ist damit abgeschlossen.