Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1364,6 +1364,15 @@ true until the next version shipped.
runner and the development loop. Without that the matrix, which builds once per
major and then sets PGC_SKIP_BUILD, would have reported every suite as unverified.

The reader for the source field now reads its first line only. Stripping hex from
the whole file was right while a stamp was one line, and wrong as soon as there were
two: a source that cannot be fingerprinted writes an empty first line, and the
whole-file read returned the library digest as the source, turning a documented
unverified into a refusal that named a library digest as a source fingerprint. That
was introduced by the second line rather than found lying in wait, so it is fixed
here. Reported by Joshua D. Drake, who swept every hex extraction in the harness to
establish it was the only one.

The refusal on a changed source had never been exercised by anyone before this
change, only read. It is now driven end to end, along with the three other states.

Expand Down
3 changes: 3 additions & 0 deletions test/check_ledger.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -352,11 +352,13 @@ harness_selftest 340-the-binary-must-be-built-from adding a source file moves it
harness_selftest 340-the-binary-must-be-built-from an added file appears in the manifest by name never -
harness_selftest 340-the-binary-must-be-built-from an added file shows up in the report never -
harness_selftest 340-the-binary-must-be-built-from an empty manifest is reported as empty, not as silence never -
harness_selftest 340-the-binary-must-be-built-from an unfingerprintable source reads as empty, not as the library digest never -
harness_selftest 340-the-binary-must-be-built-from an unhashable tree has an empty manifest never -
harness_selftest 340-the-binary-must-be-built-from an unreadable b.c yields no fingerprint, not a wrong one never -
harness_selftest 340-the-binary-must-be-built-from an unreadable c.c yields no fingerprint, not a wrong one never -
harness_selftest 340-the-binary-must-be-built-from an unreadable library is not a failure never -
harness_selftest 340-the-binary-must-be-built-from and a non-numeric timestamp is unknown rather than compared as text never -
harness_selftest 340-the-binary-must-be-built-from and a short first line does not splice the second into it never -
harness_selftest 340-the-binary-must-be-built-from and a stale source with a replaced binary is still refused for the source never -
harness_selftest 340-the-binary-must-be-built-from and an uncomputable current fingerprint is unknown, not stale never -
harness_selftest 340-the-binary-must-be-built-from and an unreadable installed library is unknown, not replaced never -
Expand Down Expand Up @@ -404,6 +406,7 @@ harness_selftest 340-the-binary-must-be-built-from premise: the tree fingerprint
harness_selftest 340-the-binary-must-be-built-from premise: the unprivileged read agrees while everything is readable never -
harness_selftest 340-the-binary-must-be-built-from premise: the writer wrote a stamp at all never -
harness_selftest 340-the-binary-must-be-built-from renaming a source file moves the fingerprint too never -
harness_selftest 340-the-binary-must-be-built-from so its verdict is unknown rather than a spurious stale never -
harness_selftest 340-the-binary-must-be-built-from so the tree still fingerprints from its root files alone never -
harness_selftest 340-the-binary-must-be-built-from so the verdict is fresh, not unknown never -
harness_selftest 340-the-binary-must-be-built-from so the verdict is unknown -- UNVERIFIED -- and never stale never -
Expand Down
2 changes: 1 addition & 1 deletion test/check_ledger_budget.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ suites_not_covered 250
# Without that it is a hand-maintained count that drifts, which is the failure
# this repository has spent a day proving. It is not a ceiling; it is a
# measurement that must be true.
checks_never_observed_red 843
checks_never_observed_red 846
20 changes: 19 additions & 1 deletion test/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -947,8 +947,26 @@ pgc_read_installed_stamp() { # pgc_read_installed_stamp FILE -> digest or empty
}

pgc_read_source_stamp() { # pgc_read_source_stamp FILE -> hash or empty
# THE FIRST LINE ONLY, and this is the mirror of the trap in the reader above
# (#959 review, @jdatcmd). Stripping hex from the WHOLE FILE was right while a
# stamp was one line and became wrong the moment this change added a second:
#
# source unfingerprintable + a digest recorded
# file "" + "d312a10c0cfb"
# whole-file read d312a10c0cfb <- the LIBRARY digest, as the source
# verdict stale <- was `unknown` before this change
# decision refuse-source <- a FATAL naming a library digest
# as a source fingerprint
#
# Before, that case wrote a one-line empty stamp, read empty, and reported
# UNVERIFIED -- which is the documented behaviour for a tree that cannot be
# fingerprinted. So the regression was introduced by the second line, not found
# lying in wait, and it belongs in this change rather than a follow-up.
#
# A short first line would also have spliced across the newline: "abc" plus
# "d312a10c0cfb" read as "abcd312a10c0".
[ -r "${1:-}" ] || { echo ""; return; }
tr -dc 'a-f0-9' < "$1" | head -c 12
sed -n '1p' "$1" | tr -dc 'a-f0-9' | head -c 12
}

# The stamp lives beside the tree that built the binary, keyed by major, because one
Expand Down
16 changes: 16 additions & 0 deletions test/selftest/340-the-binary-must-be-built-from.sh
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,22 @@ check "a two-line stamp still yields the source fingerprint first" \
"$(pgc_read_source_stamp "$_bs")" "a0e6afc3e13e"
check "and yields the library digest second" \
"$(pgc_read_installed_stamp "$_bs")" "d312a10c0cfb"

# THE MIRROR OF THAT TRAP, in the reader this change did not touch (@jdatcmd swept
# for it). `pgc_read_source_stamp` stripped hex from the WHOLE file, which was right
# while a stamp was one line. With two, a source that cannot be fingerprinted writes
# an empty first line and the whole-file read returns the LIBRARY DIGEST as the
# source: verdict `stale` instead of `unknown`, so a documented UNVERIFIED became a
# FATAL naming a library digest as a source fingerprint. Introduced by the second
# line, so it is fixed here rather than left as a residual.
pgc_write_source_stamp "$_bs" "" "d312a10c0cfb"
check "an unfingerprintable source reads as empty, not as the library digest" \
"$(pgc_read_source_stamp "$_bs")" ""
check "so its verdict is unknown rather than a spurious stale" \
"$(pgc_freshness_verdict "$(pgc_read_source_stamp "$_bs")" a0e6afc3e13e)" "unknown"
printf 'abc\nd312a10c0cfb\n' > "$_bs"
check "and a short first line does not splice the second into it" \
"$(pgc_read_source_stamp "$_bs")" "abc"
unset _bs

# The fingerprint has to MOVE when a build input moves and STAY when nothing does.
Expand Down
Loading