This Day In History For 2027-10-11
1 Year Ago (more context)
|
2026-10-11
| ||
| 23:54 |
fix(hash): default to sha3 when empty and persist the auto promotion (#274) (#323)
With no hash-policy row, NamingFor now follows fossil's hname_default_policy: sha3 if the repo holds a SHA3 artifact or no SHA1 one, auto otherwise (7.2). hash.PromoteFor, called by blob's single row writer and by sync's received-content store before an artifact enters, writes hash-policy=2 when an auto repo takes a SHA3 name (7.4), as content_put_ex does, so fossil opening the repo sees the promotion. A row still saying auto next to SHA3 artifacts, from before the promotion was written, keeps deriving sha3. check-in: cc76fd023f user: [email protected] tags: main, trunk | |
| 23:44 |
fix(manifest): reject a non-baseline as a delta manifest's baseline (#275) (#322)
ListFiles took any parseable artifact named by a B card as the baseline, so a delta manifest or a control artifact produced a partial or empty file set. Sections 4.7.3 and 8.3 require the target to be a baseline manifest: a checkin with no B card of its own. ListFiles now returns an error otherwise. check-in: 9fbe647b7f user: [email protected] tags: main, trunk | |
| 23:39 |
fix(manifest): refuse check-in filenames outside the writer profile (#270) (#321)
Checkin wrote any F-card filename it was given. The artifact format's writer profile (4.6.1) forbids a backslash and anything but valid UTF-8, surrogates and overlong forms included; fossil rejects a manifest that names one. storeFileBlobs now refuses such a name or old name before storing anything. check-in: 357d10dac6 user: [email protected] tags: main, trunk | |
| 23:34 |
fix(delta): refuse a source or target of 2^32 bytes or more in Create (#279) (#320)
The delta format holds integers below 2^32 only, so a producer must not write a target length or copy offset at or past that. Create now returns ErrTooLarge for such inputs; Deltify then stores the content whole, as fossil does when a delta is not worthwhile, and the other callers propagate the error. Apply's header check becomes >= so it refuses exactly what Create will not write. The bound is tested on lengths, as a direct test needs a 4 GiB input. check-in: 38eddf43f1 user: [email protected] tags: main, trunk | |
| 23:28 |
fix(blob): fill a phantom in place when its content is stored (#278) (#319)
blob.Store, StoreDelta and StoreDeltaRaw now share writeRow, which fills a phantom row of the same name in place (content, size, and removal from the phantom table) as fossil's content_put does, and returns that rid. existingName no longer treats a phantom as stored content, so a check-in of a file matching a known phantom stores the file instead of recording a manifest that points at nothing. check-in: 23cfc00bfe user: [email protected] tags: main, trunk | |
| 23:18 |
fix(repo): resolve version names in fossil's order and forms (#290) (#318)
ResolveVersion chose a tag by tagxref.mtime instead of the carrying check-in's event.mtime, fell back to the tip when no check-in carried sym-trunk, tried a plain name before an artifact-hash prefix, and recognized none of fossil's rid:, tag:, root:, start:, merge-in: or NAME:TIMESTAMP forms nor the trailing-punctuation retry. It is now a port of fossil's symbolic_name_to_rid (src/name.c), written as an ordered sequence of small attempts in fossil's order: tip (which, like fossil, falls through to the ordinary forms when there is no check-in), rid:, tag:, root:/start:/merge-in: (branch points, via start_of_branch and, for merge-in, the youngest ancestor in the branch), NAME:TIMESTAMP, then a 4-64 character hex prefix (tried before a plain tag, matching any artifact and reporting more than one match as ambiguous), then a plain sym- tag chosen by event.mtime, and finally a retry with one or two trailing punctuation characters removed. There is no tip fallback for an unknown name. The exported signature is unchanged; "" still means tip. NAME:TIMESTAMP now rounds the boundary UP to the last millisecond of the stated precision (fossil's fossil_roundup_date / fossil_expand_datetime): a bare date becomes 23:59:59.999, HH:MM becomes :59.999, HH:MM:SS becomes .999. The compact YYYYMMDD forms, a fractional-second suffix and a trailing Z/UTC designator are accepted; the time is read as UTC, matching fossil's default timeline-utc. Bare YYYY-MM and hour-only forms are not supported. Unit tests cover the three round-up precisions (inside/outside the window), the zulu designator and the ambiguous-prefix path. check-in: 329ce1ad02 user: [email protected] tags: main, trunk | |
| 23:06 |
fix(branch): refuse an open branch's name on create; close a branch by its tip (#292) (#317)
branch.Create accepted a name an open branch already used, letting a second branch of the same name be created; and branch.List marked a branch closed when any check-in on it carried a closed tag, so closing a non-tip check-in hid an open branch. Create now checks branch_is_open first (an open leaf whose active branch is the name) and refuses before building any artifact, so nothing is stored on refusal, matching `fossil branch new`. The check uses fossil's exact tag types: a propagating branch tag (tagtype=2) and a singleton closed tag (tagtype=1). List now derives a branch's closed state from its newest check-in's closed tag, the row fossil's branch-list query reads, so a branch with an open tip lists open. Unit tests cover the refusal, the no-stored-blob guarantee and reuse of a closed branch's name. check-in: faf47b6220 user: [email protected] tags: main, trunk | |
| 22:59 |
fix(checkout): count only open leaves for forks and fork warnings (#291) (#315)
BranchLeaves joined the leaf table without excluding leaves that carry a closed tag, so a closed leaf still counted toward a branch's leaves, and WouldFork, built on it, reported a fork for a version that was not itself a leaf. This made a closed leaf look like an open one and a non-leaf commit look like it would fork. BranchLeaves now excludes any leaf with a closed tag (tagtype>0), matching fossil's leaf_is_closed_sql, so it returns a branch's open leaves. WouldFork is now fossil's leaf_ambiguity: the current version must itself be an open leaf (is_a_leaf AND not closed) before another open leaf on the same branch can make a commit fork; a non-leaf or closed version returns false. currentBranch now surfaces a real query error instead of masking it as "trunk". Unit tests cover the open-sibling, closed-sibling and non-leaf-parent cases. check-in: f8496d12cc user: [email protected] tags: main, trunk | |
| 20:59 |
test(conformance): sync suite follows the s7.3 uvgimme Read erratum (#313)
The new erratum to draft-fossil-sync-protocol-00 §7.3 has the server answer uvgimme only for a requester with Read, with Clone implying Read, and refuse silently otherwise. fossil 2.28 answers any uvgimme. - The erratum is copied unmodified into conformance/rfcs/erratum and pinned in requirements/sync.tsv, with two new requirements, SP-7.3-11 and SP-7.3-12. - Server cases can carry a fossil note again: a case that expects something fossil(1) does not do says why, and fails once fossil(1) does it. sync.7.3.uvgimme-no-read uses it, so the case flags the day CI's pinned fossil takes the matching patch. - sync.7.3.uvgimme-clone-implies-read finds that go-libfossil's read gates ignore Clone; it is marked as a gap, tracked in #312. check-in: 2cb62c37bc user: [email protected] tags: main, trunk | |
| 13:57 |
test(conformance): sync-protocol conformance suite (#262) (#311)
* test(conformance): sync-protocol conformance suite (#262) Checks go-libfossil against draft-fossil-sync-protocol-00, requirement by requirement: 149 requirements, 199 cases. Server cases send raw requests to Repo.XferHandler and, through `fossil http --in`, to fossil(1) on a copy of the same repository; client cases drive the public Sync and Clone against a scripted peer, with fossil(1)'s client run against the same script for most of them; HTTP cases cover redirects, status codes and media types; interop cases run whole exchanges in both directions. Known failures are marked with the placeholder #0 until their issues are filed, so TestCoverage fails until then. * test(conformance): sync suite review fixes (#262) Cases for the requirements that had none where fossil(1) can show the behavior: server-version, the SHA3 gate, shun admission, cookie and cleartext logins, pushed configuration, ci-unlock, cluster brackets, the clone's unversioned catalog and the pull-only message. Two rows added: link ARG handling and the short uvigot. A fossil(1) disagreement, a harness failure or a deviation other than the one named now fails a case whatever its mark. The server's log output is discarded in the tests. * test(conformance): mark sync gaps with their issues; drop gaps v0.11.1 closed (#262) v0.11.1's read gate and redirect policy make seven sync cases conform, so their gap marks are removed. The rest are marked with the issues that track each fix: #296 and #299-#310. * test(conformance): accept either fossil refusal of a negative clone SEQNO fossil 2.28's macOS build answers clone 3 -1 with clone_seqno 0 and its Linux build, which CI pins, with the invalid-sequence error alone. The draft leaves the reply open; the case now holds go-libfossil only to sending no content. check-in: 80c72b27c7 user: [email protected] tags: main, trunk | |
| 13:33 |
•
Edit [dbe626ea5d]: Add tag "v0.11.1" with note "Release v0.11.1
This release fixes two vulnerabilities in the sync server and client. Upgrade if you serve repositories that must not be readable anonymously, or sync over HTTPS. - GHSA-mvx3-6793-8x4r (medium): the sync server sent artifacts and unversioned files to requesters without read permission. `gimme` is now answered only in an accepted pull or a clone, and the unversioned catalog and files only to readers. - GHSA-3f8x-8fr5-mr98 (low): the sync client followed a redirect from HTTPS to plain HTTP, resending the login card in cleartext. Redirects now follow fossil's rules and never downgrade. - `pragma ci-lock` takes or reports a check-in lock only for a requester with Write. fossil takes a lock for any requester; fossil's own client asks for one only before a commit, which needs Write. - An HTTP redirect is followed by re-POSTing the request, as fossil does, rather than switching to GET. c1f3fc9 chore(release): v0.11.1 changelog (#298) 2992016 fix(sync): send content only to readers; never follow HTTPS to HTTP (security) (#297) 1a8c243 test(conformance): repository-state conformance suite (#262) (#295)". artifact: 738281c7fe user: [email protected] | |
| 13:32 | chore(release): v0.11.1 changelog (#298) leaf check-in: dbe626ea5d user: [email protected] tags: trunk, v0.11.1 | |
| 13:32 | • Edit [dbe626ea5d]: Add tag "v0.11.1". artifact: a762334536 user: [email protected] | |
| 13:28 |
fix(sync): send content only to readers; never follow HTTPS to HTTP (security) (#297)
* fix(sync): send content only to requesters allowed to read it The sync server answered `gimme HASH` with the artifact whether or not a pull card had been accepted, and answered `pragma uv-hash`, `uvgimme` and `uvigot` with the unversioned catalog and files for any requester, anonymous ones included. Match fossil's page_xfer: - gimme is answered only when a pull card was accepted, or in a clone, which fossil also treats as pulling. - pragma uv-hash sends the catalog only to a requester with Read (o, i or Admin). uv-push-ok goes only to a requester with y; other readers get uv-pull-only, as fossil sends. - uvgimme and uvigot send nothing to a requester without Read, and uvigot adopts a client's mtime only for a requester with y. - Table sync follows the same rules: xgimme needs an accepted pull and pragma xtable-hash needs Read. - pragma ci-lock takes or reports a lock only for a requester with Write, so an anonymous requester cannot learn who holds one. Pragma handling moves into handlePragma to keep handleControlCard short. GHSA-mvx3-6793-8x4r * docs(changelog): note that gating ci-lock on Write departs from fossil GHSA-mvx3-6793-8x4r * fix(sync): follow HTTP redirects as fossil does, never HTTPS to HTTP Both HTTP transports used net/http's default redirect policy. It follows a redirect from HTTPS to plain HTTP, so a 307 or 308 resent the request, login card included, in cleartext. It also turns a 301 or 302 into a GET without the body and stops after 10 redirects, neither of which fossil does. PostXfer now follows redirects the way fossil's http_exchange (src/http.c) and draft §4 describe. It replaces the client's redirect policy for these requests, then: - refuses a redirect from HTTPS to HTTP, and to any scheme but http(s); - re-POSTs the same body and Content-Type for 301, 302, 307 and 308; - strips one trailing /xfer from the new location, as fossil's loop does (the draft says "repeatedly"; the code strips once); - fails on the twentieth redirect (MAX_REDIRECTS 20). HTTPTransport and NewHTTPTransport both use it, including with a client passed through WithHTTPClient. GHSA-3f8x-8fr5-mr98 check-in: 3a1014cf60 user: [email protected] tags: trunk | |
| 02:13 |
test(conformance): repository-state conformance suite (#262) (#295)
* test(conformance): repository-state conformance suite (#262) Check go-libfossil against draft-fossil-repo-state-00, requirement by requirement. Each derived-state case is a scripted sequence of artifacts loaded into go-libfossil and into fossil(1); the tables derived from it are compared row by row, joined by artifact hash. Every case runs through manifest.Crosslink, as one sweep and one artifact at a time, and most also run as a ".rebuild" case through verify.Rebuild. fossil's rows must equal each expectation on every run, and each case states what ignoring its requirement would change, so a case cannot pass or fail by accident. API cases cover name resolution, leaves, the ambiguity test, branch creation and listing, and tagging, each compared with fossil's answer on the same repository. TestRepoStateCorpus compares verify.Rebuild and a Crosslink sweep with fossil rebuild on real repositories named by CONFORMANCE_REPOS. Known failures are marked with the placeholder Gap #0 until their issues are filed, so TestCoverage refuses them for now. * test(conformance): repository-state suite review fixes (#262) - Unsorted T-card cases use a non-hex name, so the ordering rule, not the hex-name rule, is what rejects them. - RS-4.2-7 crosslinks every artifact a second time over the rows the first left (repostate.4.2.relink-unchanged), instead of a sweep that links nothing. - RS-7.3-2, -3 and -4 are checked through manifest.Checkin and branch.Create, which maintain leaves one check-in at a time; a crosslink sweep recomputes the whole table. - retag-branch is built so the retagged check-in's own leaf status changes; branch membership is read through BranchLeaves, and the tagxref case it replaced is reattributed to RS-5.4-5; bad-prefix also compares tagxref. - parentless-untagged follows the draft and marks go-libfossil's crosslink, which follows fossil(1), as a deviation; the unused draft field becomes fossil, checked against fossil's rows. - Every fossil(1) command, in all suites, runs with HOME, FOSSIL_HOME and XDG_CONFIG_HOME in the test's directory, so it no longer records checkouts in the user's global configuration. * test(conformance): mark repository-state gaps with their issues (#262) Replace the placeholder gap marks with the issues that track each fix: #278 and #285-#294. check-in: 7fa0b9b5da user: [email protected] tags: trunk | |
| 01:39 |
•
Edit [59df292529]: Add tag "v0.11.0" with note "Release v0.11.0
This release fixes five vulnerabilities. Upgrade, and check existing repositories' `nobody` capabilities (see the upgrade notes). - GHSA-2g5p-q5f3-477p (high): a captured login card could be replayed with any request body. The nonce is now checked against the body, as fossil does. - GHSA-44p2-whvx-9gwq (high): new repositories let anonymous users push and gave them Setup, and an account with no password accepted any login. New repositories now get fossil's default users and capabilities. - GHSA-9fq6-h6xw-274g (high): table-sync row keys from a peer were written into SQL unchecked. - GHSA-p6w4-4xqc-jhq2 (medium): `reqconfig` disclosed any config row, including `project-code`, to anyone. - GHSA-j99p-mw22-69c8 (medium): malformed sync messages from a peer could panic, or exhaust the memory of, the client or server. - `Checkout.Merge` merges the way fossil does, and `Commit` records the merge with its parents (#244). - `Repo.Annotate` credits lines the way `fossil annotate` does (#253, #256, #257). - Clone and sync exchanges follow the sync draft (#255). - Check-in, link and tag rows are stored as fossil stores them (#258). - A pull-only `Sync` converges when the client holds artifacts the server lacks (#277). - A conformance suite checks go-libfossil against the Fossil artifact and delta drafts (#262). - New repositories no longer let anonymous users push. `nobody` gets fossil's `gjorz`. - Logins to accounts with no stored password are refused. - The CLI's `ci` commits the checkout, and its `--parent` flag is gone (#244). - To allow anonymous push, grant it explicitly, e.g. `repo.SetCaps("nobody", "gijoryz")`, or give clients an account with a password. - Existing repositories keep their stored capabilities. Tighten ones created by earlier versions with `SetCaps("nobody", "gjorz")`. 6279ad9 chore(release): v0.11.0 changelog (#283) 1f7116d fix: harden sync and repository defaults (security) (#282) 1fa00d3 fix(sync): a pull-only sync converges when the server lacks the client's artifacts (#277) (#281) 877f491 test(conformance): delta-format conformance suite (#262) (#280) 6c90ce8 test(conformance): artifact-format conformance suite (#263) (#276) 5ddb0a9 test(conformance): harness for an RFC conformance suite (#262) (#264) f7481d6 Store check-in, link and tag rows as fossil does (#258) (#261) 5b1d9e8 Clone and sync exchanges follow the sync draft (#255) (#260) 10a01b4 fix(annotate): credit lines the way fossil annotate does (#256, #257) (#259) f80fa74 fix(annotate): credit lines through the start-version mapping (#253) (#254) de9aedc fix(checkout): merge the way fossil does, and commit merges with their parent (#244) (#252) ef6f656 ci(release): drop the downstream dispatch to EdgeSync (#251)". artifact: 7017cd0071 user: [email protected] | |
| 01:38 | chore(release): v0.11.0 changelog (#283) check-in: 59df292529 user: [email protected] tags: trunk, v0.11.0 | |
| 01:38 | • Edit [59df292529]: Add tag "v0.11.0". artifact: f27ad2be58 user: [email protected] | |
| 01:34 |
fix: harden sync and repository defaults (security) (#282)
* fix(xfer): reject non-decimal card sizes and bound payload memory A payload card's size was parsed with strconv.Atoi, so a peer sending `file HASH -1` reached readPayload's negative-size assertion and panicked the client or server decoding the message, and a signed size such as `+5` was accepted. Sizes now go through parseSize, which follows the sync draft's `decimal = 1*DIGIT` grammar and fossil's 32-bit limit and returns a decoding error for anything else. uvfile FLAGS use the same parser, so negative FLAGS are rejected as the draft requires. The assertion stays, now unreachable from peer input. readPayload no longer allocates the declared size up front: its buffer grows with the bytes read, so a large size over a short message fails after allocating about what was sent. A cfile payload may inflate only to its USIZE (a margin above it for a delta) and not past its 4-byte size prefix, and all cfile payloads in one message share a MaxCFileInflateBytes (1 GiB) budget, so a few megabytes of zlib cannot inflate to tens of gigabytes. FuzzDecode exercises the decoder over both framings. * fix(sync): refuse malformed xrow payloads and cap HTTP reply bodies An xrow payload or xdelete PKData from a peer was decoded into a map and used as is. JSON null gave a nil map that reached coerceJSONNumbers' assertion, and a primary-key value of the wrong type or a nested value reached normalizeValue's, panicking the client or server. Both directions now decode through decodeRowJSON: one JSON object, nothing after it, and repo.ValidateRow's rules, which require scalar values and primary-key values that PKHash can normalize. A client refuses an xrow for a table it has not registered. Column types match case-insensitively, as table creation accepts them. Both HTTP transports read replies through xfer.ReadBody, which stops at MaxBodyBytes (MaxDecompressedBytes plus framing headroom) and returns ErrBodyTooLarge, untagged for retry, instead of reading an endless body into memory. FuzzTableSyncPayload drives the server handler and client over arbitrary payloads. * fix(sync): check synced-table rows and identifiers before building SQL repo.UpsertXRow wrote a row's map keys into its INSERT as column names, and the rows of an xrow payload or xdelete PKData come from the peer, so a key such as "val, mtime) VALUES(...) --" chose the statement's columns and values, and a key could select from other tables into a synced one. This held on the server for pushed rows and tombstones, and on the client for a server's rows. A peer's row must now use exactly the table's declared columns: repo.ValidateRow refuses any other key, which also keeps a peer from setting _owner. UpsertXRow no longer trusts its caller: it reads the table's registered schema and refuses any key it does not declare, apart from _owner on an ownership-mode table. ListXRows, LookupXRowOwner and DeleteXRowByPKHash validate the table name and the column names they interpolate, so no synced-table identifier reaches SQL text unchecked. * fix(sync): answer reqconfig only with fossil's transferable config The sync server answered reqconfig NAME with any row of the config table, for any requester, including one with no capabilities, so project-code, server-code and every local setting could be read by anyone who could reach the sync endpoint. handleReqConfig now follows fossil's page_xfer and configure.c. It answers only a /GROUP name, only for a requester with Read, matches the group by prefix in fossil's table order, and sends only the names fossil transfers in that group, in fossil's encoding. The user and subscriber tables also need Admin, which counts only for a verified login, and the concealed table needs RdAddr. A refused request gets no cards and no error. The groups, their names and their capability rules live in one place, config_groups.go. A differential test answers the same requests with fossil's own server and with HandleSync on the same repository and requires identical config cards. * test(sync): keep fossil http from leaving a backoffice process * fix(sync): check the login nonce against the request body The server verified a login card's signature over its nonce but never checked that the nonce was the SHA-1 of the request body after the login line, as fossil's check_tail_hash does (draft-fossil-sync-protocol-00 §6.2). A login card captured from one request therefore authenticated any other request body. The decoder now records, for each login card, the SHA-1 of the decompressed bytes after the card's line, and VerifyLogin refuses a card whose nonce does not match it. A login card that was never decoded has no tail and is refused. Login handling otherwise follows fossil's page_xfer and check_login: - a refused login ends the exchange with "error login failed" instead of continuing as nobody; - a second login card is refused with "multiple login cards"; - a successful login adds the user's capabilities to nobody's instead of replacing them; - nobody and anonymous log in without a password, and the reserved developer and reader logins and accounts with an empty password cannot be logged into. Fixes GHSA-2g5p-q5f3-477p. * fix(repo): seed nobody with fossil's default capabilities A new repository seeded the nobody user with "cghijknorswy", so every request without a login card could push check-ins and unversioned files, write wiki pages and tickets, and held Setup. Seed the four built-in users `fossil new` creates, with fossil's capabilities: nobody "gjorz", anonymous "hz", developer "ei" and reader "kptw". Setup and Admin now include check-in, read and clone, as they do in fossil, so the creating user can sync once given a password. A login to an account with no stored password is refused, as fossil's check_login refuses it; the creator starts with none, and the signature would otherwise be the SHA-1 of the nonce alone. Tests that push without credentials grant nobody push explicitly. Existing repositories keep their stored capabilities. * test(auth): reserved-login test updates the seeded developer and reader rows New repositories now seed developer and reader as fossil does, so the test gives the existing rows a password instead of inserting them. * docs(changelog): group the sync hardening fixes under Security * test(sync): reqconfig tests sign their logins over the request body The login nonce now has to cover the request body, so the reqconfig tests build their admin requests with signedRequest instead of a bare login card. check-in: 3a6126c3e9 user: [email protected] tags: trunk | |
| 01:15 |
fix(sync): a pull-only sync converges when the server lacks the client's artifacts (#277) (#281)
The server answered a pull-only client's igot cards with gimme for artifacts it lacked. The client was not pushing, so it never sent them and kept going round after round until it hit the round cap. Fossil's page_xfer handles igot only when the client sent a push card, and does the same here: a pull-only igot just records what the client has. The client also treated the server's gimme cards as outstanding work even when it was not pushing, so any server that did ask (an older libfossil, or another implementation) could hold a pull open. A session without push now ignores gimme cards. Two handler tests relied on a pull card alone producing a gimme; they now send a push card. check-in: 1e3e2df2f2 user: [email protected] tags: trunk | |
| 01:07 |
test(conformance): delta-format conformance suite (#262) (#280)
* test(conformance): delta-format conformance suite (#262) Check internal/delta against draft-fossil-delta-format-00, requirement by requirement: 39 requirements, 88 cases. Decoder cases (Apply and OutputSize) are byte vectors, each also given to fossil(1) through its SQL delta functions; fossil's verdict must match unless the case records why it follows the draft instead (fossil masks the high bit, does not verify the checksum, and returns the size as a signed int). Each rejection breaks one rule and keeps the trailer valid, so check order cannot hide the rule under test. Producer cases check Create against a strict oracle and against fossil's delta_apply, and fossil's delta_create against Apply. FuzzDeltaApply compares Apply with an independent model decoder; FuzzDeltaRoundTrip checks Apply(Create(s, t)) == t. DF-3.1-6 (Create has no 2^32 bound) has no case: it needs a 4 GiB input. * test(conformance): delta suite names the reason each rejection must give A rejection case could pass because some other rule rejected the input. Every rejection case now names a substring of go-libfossil's error (or ErrChecksum), and the harness fails the case when the message differs. Vectors that were rejected for the wrong reason are fixed or reattributed: copy-truncated (DF-4-2), reject-10-nul (non-empty count, so the NUL is the opcode), copy-overflow-64 (DF-4-11), and high-bit-count, which now tells a masking decoder from a conforming one (fossil accepts it). The phantom-base case uses a literal-only delta; the content-discard case checks ErrChecksum and the store-side header refusals move to DF-4.1-3. The allocation bound gets its own row (DF-6-5) and takes the least of five runs. DF-3.1-6 notes issue #279. Drops a duplicate size-query case, the sizeCase helper and the decorative fuzz guard bytes. check-in: 0629de2beb user: [email protected] tags: trunk | |
| 00:42 |
test(conformance): artifact-format conformance suite (#263) (#276)
* test(conformance): artifact-format conformance suite (#263) Adds the suite for draft-fossil-artifact-format-00 with errata 4.1.2, 4.2 and 4.6.4, so the parser, writer, naming, hash policy and delta manifest code are checked requirement by requirement instead of by scattered unit tests that each encode one reading of fossil. - requirements/artifact.tsv: 101 requirements from Sections 3 to 8, pinned to the draft and the three errata. - Parse cases are a known-good base artifact per type plus one edit, with the Z card recomputed, so the edit alone explains a rejection. Every case also runs through fossil test-parse-manifest; fossil 2.28 agrees with all of them. Card legality, duplicates, arity and hash positions are generated from the bases and the draft's own tables. - Accepted inputs must re-encode byte for byte unless marked non-canonical. - API cases cover naming, verification, the comparator, the writer, the R card, the hash policy and delta-manifest enumeration. - FuzzArtifactRoundTrip checks parse/marshal/parse stability, and TestArtifactCorpus (CONFORMANCE_REPOS) parses every artifact fossil crosslinked in real repositories. 267 cases go-libfossil fails are marked with a "#0" placeholder in artifact_gaps_test.go, grouped by the code at fault, for issues to be filed against. * test(conformance): tighten the artifact suite after review (#263) A rejection only counts when the rule the case names makes it, so every rejection case that is not about the Z card must now pass deck.VerifyZ first. Inputs go-libfossil rejected only through the Z check (framing, residue, sterilizer, unstripped wrappers, an extra Z token) become gaps, along with VerifyZ itself, which rejects an absent Z card and reads the last byte where Section 6.2 says it must not. - Cases can name the substring fossil's rejection reason must contain; the unknown-letter cases sit in sorted position, the sterilizer cases are filed under card order, which is what fossil rejects them for, and generated legality cases take their requirement from the draft's table. - The ratchet that never persists the hash policy is a gap: fossil opening the repository still reads auto. - New rows for 4.7.9, 6.2 (absent Z, last byte), 6.3.4 and 7.1. - The audit refuses the #0 placeholder, a test keeps the gap map and the fuzz test's forgiven losses tied to live gap cases, and one Z-card helper replaces two. * test(conformance): mark artifact gaps with their issues (#263) Replace the placeholder gap marks with the issues that track each fix (#265-#275), and keep coverage_test.go within 100 columns. check-in: d52a6fe050 user: [email protected] tags: trunk | |