search, seek, delete und update.rdb lesen bei -mh, -mi, -mr nur Indexeintrag und Satz. Hashindizes (.h) müssen neu gebaut werden. total, mean, subtotal und die /act-Befehle rechnen mit BigDecimal, gerundet wird halb auf.
6.7 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 (BigDecimalintotal/mean/subtotalund /act). Ursprünglich: (act.rb:11,to_fim /act-Teil und intotal). Abhilfe:BigDecimaloder ganzzahlige Rappen. - awk-Brücke (env.rb:119-138): ganze Tabelle als String
durch
capture3, kein Streaming; handgeschriebener Parser erkennt Strings und Regexe heuristisch (prev) und hängt vom awk-Dialekt ab. - Globale Methoden auf
Object(fast_opts,lock_file,num,money,ask,need,show_record…). In ein Modul kapseln und inEnveinbinden. - Doppelter Code.
awk/awk_text; Schlüsseltabellen-Parsing infast_opts/key_columns; von Hand gebaute Kopf-/Strichzeilen trotzTable.dash_row. - Tests. Laufzeit ca. 66 s wegen eines Ruby-Prozesses pro Test. Fehlerfälle
(Encoding, Tab in Wert, Locks, Editor) nicht abgedeckt; Tests direkt gegen
Rdb.runim Prozess wären schneller. - Repo.
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 Verbesserung 1–3 sind erledigt. Offen sind 4–8: die
awk-Brücke, globale Methoden auf Object, doppelter Code, Testlaufzeit, Repo-Aufräumen.