pgw#973 §4.24 wave 2: six safetensors header caps become one, plus three duplicate bounds and two false justifications - #509
Open
PaulFidika wants to merge 3 commits into
Open
pgw#973 §4.24 wave 2: six safetensors header caps become one, plus three duplicate bounds and two false justifications#509PaulFidika wants to merge 3 commits into
PaulFidika wants to merge 3 commits into
Conversation
PaulFidika
force-pushed
the
973-limits-wave2
branch
from
August 6, 2026 20:39
ace3187 to
487aa36
Compare
…ree duplicate bounds and two false justifications
ONE THREAT, ONE NUMBER (the headline). A safetensors file opens with an
8-byte declared header length read straight from the file, and every reader
turns it into json.loads(f.read(n)) before anything has validated it. That
threat was stated six times: w4a4, w8a8, svdq, loading and convert/ingest at
100 MiB, convert/writer at 512 MiB.
The outlier was a live defect, not just noise: writer accepted headers
loading refuses, so the re-shard path could emit a shard the serving path
could not open. Same bytes, two verdicts.
All six now read models/safetensors_header.py, where the threat, why nothing
else prevents it (the length is read before any other structure exists), and
why 100 MiB is a plausibility floor rather than a measurement are stated
once — with what would change it.
DELETED, dead: models/memory.py _DEFAULT_VAE_SLICE_THRESHOLD_GB = 10.0, zero
references in src, tests, docs or scripts.
SINGLE OWNER, duplicated value: _READ_CHUNK_BYTES (chunk_cas already exports
the chunk vocabulary chunk_upload imports).
CENSUS CORRECTED — input_assets vs url_fetch is NOT two caps on one path.
open_guarded_stream deliberately caps nothing ("the caller owns the read and
its byte cap"); fetch_bytes and _download_one are separate entry points each
enforcing its own. Acting on the filed verdict literally would have left one
path with no cap. Aliased to one owner instead of deleted.
CENSUS CORRECTED — _PRESIGNED_PUT_BUDGET is not the authoritative cap and is
not deletable either. Its justification cited _concurrent_upload.py, a module
that NO LONGER EXISTS, and claimed file-level fan-out of 4; the only in-repo
caller is sequential, so the file axis is 1 and min(total_parts, 4) is what
binds. It is KEPT because it covers the one axis optimal_part_concurrency
cannot see — an endpoint author calling ctx.save() from their own threads —
and both docstrings now say that instead of citing each other.
Proof: tests/test_one_safetensors_header_bound_pgw973.py — real files on
disk through every real entry point, no mocks and no monkeypatching of the
bound. The runaway (2**63-1), the over-cap and the absent (0) length are
refused at all six; a legitimate file still parses at all six; writer and
loader now agree on a 200 MiB-declared header. A structural pin fails the
suite if any module re-declares a header cap.
RED-verified: restoring 512 MiB in convert/writer.py fails
test_writer_and_loader_agree_on_the_same_file — the writer accepts the
length and only trips later on the short body, i.e. it would have attempted
the 200 MiB read.
Gates: tests/ 3297 passed, 37 skipped, 1 xfailed (the single -n 4 failure,
test_procsplit_pgw763, passes in isolation — load-induced, untouched by this
change); test_import_cycles_pgw981 green (the new leaf module adds no cycle).
Python 3.12.
Aliasing it to url_fetch's copy meant importing a private name across modules to de-duplicate something §4.24 does not reach: a 1 MiB streaming read buffer refuses nothing, so it is not a limit and sharing it buys no threat coherence. Only DEFAULT_MAX_BYTES — which does refuse — stays aliased to its single owner. Labelled in place so the next census does not re-file it.
scripts/assemble_changelog.py requires <prefix><number>.md — the number is what orders the release section — so 'pgw973-wave2.md' would have failed the cut, not the PR. Same issue, same file, no sibling lane touches it. (Pre-existing and untouched: changelog.d/pgw868-a4.md violates the same rule on master and belongs to the pgw#868 A1 lane.)
PaulFidika
force-pushed
the
973-limits-wave2
branch
from
August 6, 2026 21:03
b7cddf2 to
90b7e0d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Executes the tabled §4.24 verdicts from the pgw#973 census against current
master. Every verdict was re-verified before acting — two were wrong in a way that would have removed a real bound, and both corrections are recorded rather than quietly worked around.The headline: one threat, one number
A safetensors file opens with an 8-byte declared header length read straight from the file, and every reader turns it into
json.loads(f.read(n))before anything has validated it. That threat was stated six times:models/w4a4.py,models/w8a8.py,models/svdq.py,models/loading.py,convert/ingest.pyat 100 MiB — andconvert/writer.pyat 512 MiB.The outlier was a live defect, not just noise: the writer accepted headers the loader refuses, so the re-shard path could emit a shard the serving path could not open. Same bytes, two verdicts.
All six now read
gen_worker.models.safetensors_header, where the threat, why nothing else prevents it (the length is read before any other structure exists), and why 100 MiB is a plausibility floor rather than a measurement — with what would change it — are stated once.Surviving-bound proof (
tests/test_one_safetensors_header_bound_pgw973.py): real files on disk through every real entry point, no mocks and no monkeypatching of the bound. The runaway (2**63-1), the over-cap, and the absent (0) length are refused at all six; a legitimate file still parses at all six; writer and loader now agree on a 200 MiB-declared header. A structural pin fails the suite if any module re-declares a header cap.RED-verified: restoring 512 MiB in
convert/writer.pyfailstest_writer_and_loader_agree_on_the_same_file— the writer accepts the length and only trips later on the short body, i.e. it would have attempted the 200 MiB read.Also deleted / de-duplicated
models/memory.py:_DEFAULT_VAE_SLICE_THRESHOLD_GB = 10.0— zero references in src, tests, docs or scripts._READ_CHUNK_BYTES(4 MiB), defined identically inchunk_cas.pyandchunk_upload.py— the latter already imports the rest of the chunk vocabulary from the former.Two census corrections
1.
input_assetsvsurl_fetchis NOT two caps on one fetch path.open_guarded_streamdeliberately caps nothing ("the caller owns the read and its byte cap"), andurl_fetch.fetch_bytes/input_assets._download_oneare separate entry points that each enforce their own. Acting on the filed DELETE-REDUNDANT verdict literally would have left one path with no cap at all. The value is aliased to one owner instead.2.
_PRESIGNED_PUT_BUDGETis neither authoritative nor deletable. Its justification claimed "file-level fan-out is fixed at 4" and cited_concurrent_upload.py— a module that no longer exists. The only in-repo caller is sequential, so the file axis is 1 andoptimal_part_concurrency'smin(total_parts, 4)is what binds. The semaphore is KEPT because it covers the one axisoptimal_part_concurrencycannot see: an endpoint author callingctx.save()from their own threads. Both docstrings now say that instead of citing each other.Not done here
_ARM_TIMEOUT_S's leader-progress-marker protocol change is already owned by pgw#892, which carries the exact task and a RED criterion — no new issue needed, cross-referenced instead. The remaining DELETE-NO-THREAT tranche is tabled in the tracker with per-bound verdicts, because several bounds the census swept in (_MAX_RESOLVE_BODY,_MAX_WALK_DEPTH,RENEW_FRACTION,_FINALIZE_TIMEOUT_Sas a derivation basis) have real threats and are KEEP-BUT-DOCUMENT, not deletes.Gates
Python 3.12.
tests/— 3297 passed, 37 skipped, 1 xfailed. The single-n 4failure (test_procsplit_pgw763) passes in isolation and is untouched by this change (load-induced; box load was 17).tests/test_import_cycles_pgw981.pygreen — the new leaf module adds no cycle. Changelog fragmentchangelog.d/pgw973-wave2.md. Commit signature-verified.