Skip to content

Fifteen sites read a case-guarded value into $(( )) and four issues have each fixed a subset by hand — the hand-fixing is the defect #332

Description

@fdaviddpt

Filed out of PR #331, which fixed six of them. This is the pattern, not another instance.

The count

10# has now been added, one issue at a time, by #321, #325, #329 and #331. Seven sites still read a case-guarded value straight into $(( )) with no 10#:

File Variable
scripts/post-tool-hook.sh:302 LAST_LINE
scripts/session-start-hook.sh:875 DELIVERIES
scripts/save-session.sh:342 _prev_count
scripts/run-consolidation.sh:213,218 staging_consumed
scripts/log.sh:1213 prev
scripts/lib-lock.sh:191 _mtime
scripts/doctor.sh:261 _mtime

Fifteen sites total across four issues. Each issue was correct about the sites it named and silent about the rest, so each fix looked complete and none was.

Why the guard does not guard

case "$X" in ""|*[!0-9]*) X=0 ;; esac rejects non-digits. 08 and 09 are all digits, so they pass — and then $(( )) reads them as octal and refuses. The guard's whole premise is a corrupt marker, and the two values it cannot handle are the ones a zero-padded timestamp or counter produces.

Bounded, which is what keeps this finite: [ "$x" -lt "$y" ] parses base 10 without complaint ([ 08 -lt 9 ] is true, no diagnostic). $(( )) is the only sink. So the sweep is enumerable rather than open-ended.

Why a helper alone is not the answer

The obvious fix is _remember_epoch_or_zero in scripts/log.sh, which the hooks and save-session.sh all source. That would cover almost every site — and it changes the sourcing contract for every hook in a repo that has taken ten Windows issues from seven external reporters. Worth doing, worth doing on its own, and not worth bundling into a bugfix PR.

The part that actually prevents recurrence is a lint rule, because the failure mode is a new call site written next month by someone who never read any of these four issues:

A repo-local check in the test suite is probably enough — it needs no new dependency and it fails in the one place people look.

What this is really about

Four issues, four correct partial fixes, and the tracker still holding the same defect. Fixing instances by hand is what produced #327: an issue whose own inventory said "10# appears in save-session.sh and lib-lock.sh and nowhere else" was already out of date when it was filed, because #329 had added two more sites. Every hand-fix invalidates the next issue's inventory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions