aboutsummaryrefslogtreecommitdiffstats
path: root/tests/run-tests.sh
diff options
context:
space:
mode:
authorDouglas B. Rumbaugh <doug@douglasrumbaugh.com>2026-06-06 13:44:00 -0400
committerDouglas B. Rumbaugh <doug@douglasrumbaugh.com>2026-06-06 13:44:00 -0400
commitc102ab995f9a86a77e40b9a952b2b23c0bd7de74 (patch)
treed51b9a8f1a55f7f6e6e5afb89d524b9baa350f45 /tests/run-tests.sh
parentb56c273d8198ae6cee69bbc9fe5a6a61da4074e4 (diff)
downloadbibutils-c102ab995f9a86a77e40b9a952b2b23c0bd7de74.tar.gz
Fuzzing with associated fixes
Diffstat (limited to 'tests/run-tests.sh')
-rwxr-xr-xtests/run-tests.sh57
1 files changed, 57 insertions, 0 deletions
diff --git a/tests/run-tests.sh b/tests/run-tests.sh
index 8a9f49a..653f838 100755
--- a/tests/run-tests.sh
+++ b/tests/run-tests.sh
@@ -74,6 +74,63 @@ check "bib-add -f replaces entry" grep -q ' year = 1985,' "$db"
n=$(grep -c '^@article{junk-key,' "$db")
[ "$n" = 1 ] && ok "bib-add -f leaves one copy" || not_ok "bib-add -f leaves one copy"
+# ---- bib-add hardening --------------------------------------------------
+check "bib-add writes a backup on modify" \
+ sh -c "cmp -s '$db.bak' /dev/null; [ -s '$db.bak' ]"
+
+# replacement must not disturb other bytes (comments, formatting)
+cat > "$tmpd/pres.bib" <<'EOF'
+% Encoding: UTF-8
+% hand-maintained; do not reformat
+
+@ARTICLE{ keep , AUTHOR = "Stays Verbatim", YEAR = 1111 }
+
+@article{swap2000old, author = {Old One}, title = {Swap}, year = 2000}
+EOF
+printf '@article{swap2000old, author = {New One}, title = {Swap}, year = 2000}\n' \
+ | bib-add -f "$tmpd/pres.bib"
+check "bib-add -f preserves comments" grep -q '^% Encoding: UTF-8$' "$tmpd/pres.bib"
+check "bib-add -f preserves untouched entries verbatim" \
+ grep -q 'AUTHOR = "Stays Verbatim"' "$tmpd/pres.bib"
+check "bib-add -f swapped the entry" grep -q '{New One}' "$tmpd/pres.bib"
+n=$(grep -c 'swap2000old' "$tmpd/pres.bib")
+[ "$n" = 1 ] && ok "bib-add -f removed the old version" \
+ || not_ok "bib-add -f removed the old version"
+
+# bogus input must never modify the database
+cp "$db" "$tmpd/before"
+printf '@article{, author = {No Key}, year = 1}\n' | bib-add "$db" 2> /dev/null \
+ && not_ok "bib-add rejects empty keys" || ok "bib-add rejects empty keys"
+printf '@misc{same2, title={A}}\n@misc{same2, title={B}}\n' \
+ | bib-add "$db" 2> /dev/null \
+ && not_ok "bib-add rejects dup keys within input" \
+ || ok "bib-add rejects dup keys within input"
+check "database untouched after rejected input" cmp -s "$db" "$tmpd/before"
+
+# concurrent writers serialize; no entries lost, lock released
+i=0
+while [ "$i" -lt 10 ]; do
+ i=$((i + 1))
+ printf '@misc{lock%d, title = {L %d}}\n' "$i" "$i" \
+ | bib-add "$tmpd/lock.bib" 2> /dev/null &
+done
+wait
+n=$(bib-ls "$tmpd/lock.bib" | wc -l)
+[ "$n" -eq 10 ] && ok "concurrent bib-add loses no entries" \
+ || not_ok "concurrent bib-add loses no entries (got $n)"
+[ -e "$tmpd/lock.bib.lock" ] && not_ok "lock released after use" \
+ || ok "lock released after use"
+
+# a stale lock from a dead process is reaped
+echo 999999 > "$tmpd/lock.bib.lock"
+printf '@misc{lock11, title = {L 11}}\n' | bib-add "$tmpd/lock.bib" 2> /dev/null
+check "stale lock reaped" grep -q 'lock11' "$tmpd/lock.bib"
+
+mkdir "$tmpd/adir"
+printf '@misc{k, title={T}}\n' | bib-add "$tmpd/adir" 2> /dev/null \
+ && not_ok "bib-add refuses non-regular files" \
+ || ok "bib-add refuses non-regular files"
+
# ---- bib-extract -------------------------------------------------------
cat > "$tmpd/all.bib" <<'EOF'
@article{alpha2020one, author = {A. Alpha}, title = {One}, year = 2020}