Repository navigation
Fix SIGFPE on n=0 and silent wrong output from n=11 in math/catalan.c - #1595
Open
newmathphys wants to merge 1 commit into
Open
newmathphys wants to merge 1 commit into
newmathphys wants to merge 1 commit into
Conversation
newmathphys
requested review from
Panquesito7,
alexpantyukhin and
tjgurwara99
as code owners
October 21, 2026 19:44
newmathphys
pushed a commit
to newmathphys/kern
that referenced
this pull request
Oct 21, 2026
Upstream contribution: - The minimal fix for the two defects KERN found in TheAlgorithms/C math/catalan.c was submitted as TheAlgorithms/C#1595 (22,554 stars, one file, +7 -0, CI `triage` passed). Fork newmathphys/C, branch fix/catalan-zero-and-overflow, commit 94553ec from base master@e5dad3fa. - PR text and the patch as submitted live in docs/pr/; the patch was verified with `patch -p1` on a clean checkout. - The link is recorded in docs/SHADOW_AUDIT_EXAMPLE.md, README.md, README.ru.md and journal entry #319 (RU + EN). Also in this release (already on main after the v2.6.2 tag): - #318 fixed: false [CRASH PATH] on a guarded division; path conditions are now resolved per position instead of accumulated. Version bumped to v2.6.3 across src/main.zig, src/next/main.zig, src/capi.zig, server.json, action.yml, smithery.yaml, MCP manifests, README.md, docs/index.html and docs/facts.json; CHANGELOG section added. Gates: ci-fast 10/10, version-check, metrics-guard, llms-check, sync-check, docs-parity, changelog-check, xray-check, arith-semantics-check, codecheck - all green.
newmathphys
pushed a commit
to newmathphys/kern
that referenced
this pull request
Oct 22, 2026
…s tracking
DEFECT #330. The .gitignore exception
!docs/evidence/*.log
applies ONLY to the TOP LEVEL of the directory. Logs in SUBdirectories -
`div_guards/`, `leaderboard/`, `live_eval/`, `arith_semantics/`, `external/`,
`claims_audit/`, `megatest/`, `full_arsenal/`, `prime_sieve/`, `step4_while/`,
`step8_evm/`, `live_bughunt/` - were silently ignored, so 46 files that the
documentation LINKS TO were not in the repository. An external auditor who
followed such a link got a 404: the prose promised evidence that did not exist.
Measured before the fix:
git check-ignore -v docs/evidence/external/verification.log
-> .gitignore:54:*.log
files on disk under docs/evidence/ but NOT in git: 46
That is the same class as #320 (a claim without a command that reproduces it),
which is why it matters more than a missing file usually would.
FIX
* .gitignore: added `!docs/evidence/**/*.log` (plus .json, .txt, .jsonl)
with a comment explaining WHY the single-star version was not enough;
* all 46 files staged;
* tools/evidence_gate.py now walks docs/evidence/ RECURSIVELY and fails when
any file there is not tracked, printing the list and the exact .gitignore
remedy.
NON-VACUITY: `git rm --cached` of one log turns the gate red (rc=2), then the
file is restored and the gate is green again.
A HARNESS DEFECT FOUND BY RUNNING THE CASE. The first version of the can-fail
case did `git rm --cached` and left it there. The harness rolls back FILES from
its snapshot but does not touch the INDEX, so after one run the log stayed
untracked and `evidence-gate` was red permanently - the case broke the next
run. The case is now self-healing: it removes the file from the index, runs the
gate, restores the index in the same shell command, and returns the GATE's exit
code, not `git add`'s. Verified: PASS, non-vacuous, index clean afterwards.
ALSO IN THIS COMMIT (step B, remaining items)
docs/evidence/external/verification.log - what OUTSIDE parties confirmed:
Codecov on TheAlgorithms/Rust#1075: ci_passed true, base 30441 lines /
95.89% -> head 30448 / 95.89%, "all modified and coverable lines are
covered by tests";
TheAlgorithms/C#1595 open, mergeable, +7/-0, 0 comments;
TheAlgorithms/Rust#1075 open, mergeable, +16/-0, 1 comment (the Codecov
bot; no maintainer response yet);
release v2.6.4 draft=false with 4 assets INCLUDING kern.intoto.jsonl and
kern.intoto.sig, so the binary can be verified against the public key.
Registry: 191 targets, CHECK 152/152, 174 can-fail cases.
Gates: ci-fast, claims-audit, evidence-gate, metrics-guard, llms-check,
sync-check, docs-parity, version-check, secrets-check, contracts, audits,
codecheck - all green.
This branch has not been deployed
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.
math/catalan.chas two defects. The first was reported before (#686, opened 2020-10-19, closed 2021-02-17) but the file still contains it.1. Crash on
n = 0factorialinitialises its accumulator asfac = x(line 9). Forx = 0the loop body never runs, sofactorial(0)returns0— while0!is1. Line 25 then computesf1 / (f2 * f3)with integer division, so withn = 0the divisorfactorial(1) * factorial(0)is1 * 0 = 0:2. Silent wrong output from
n = 11f1 = factorial(2 * n)must fit inlong int.20! = 2432902008176640000fits;22! = 1124000727777607680000does not. Beyond that the product overflows and the program prints garbage with exit code 0:16796.00-65.00-2.000.000.00A silent wrong answer is worse than a crash: nothing signals that the number is meaningless.
Note for reviewers — the obvious fix is wrong
Changing
fac = xtofac = 1does not work. The loop multiplies by(x-1), (x-2), …, 1, so it isfac = xthat yieldsx!. Withfac = 1the function returns(x-1)!andn = 5prints126.00instead of42.00.The fix
Keep
fac = x, handlex == 0explicitly, and guard the range that the factorial formula cannot serve:Verification after the patch
The change is intentionally minimal (bug fix only). Happy to convert
main()toassert()-based tests as suggested inCONTRIBUTING.mdif you prefer that in the same PR — just say so.How the first defect was found
Not by reading the code, and not by the program's own tests: by stating a contract and letting a solver refute it. The divisor obligation
factorial(n+1) * factorial(n) > 0was refuted with the counterexamplen = 0, result = 0, and the counterexample was then reproduced bygccon the unmodified file — see KERN, which documents the case indocs/SHADOW_AUDIT_EXAMPLE.md.The second defect (the overflow) came from arithmetic reasoning about
22!versus2^63 - 1, not from the solver.