fix(graph): fvc_search self-protects its FVC_MAX_VERTICES stack buffers (RG-2 #2) - #74
Merged
Conversation
Closes the RG-2 adversarial finding #2. fvc_search is exported in graph.h and its inner fvc_bb uses stack arrays seen[]/forbid[] sized to FVC_MAX_VERTICES (128). The cap was enforced only in the head builtin_find_vertex_coloring, not in fvc_search, and FVC_MAX_VERTICES is not visible in graph.h -- so a cross-TU caller passing n > 128 could not discover the precondition and would overflow those buffers. fvc_search now refuses (return 0) when n > FVC_MAX_VERTICES, locating the invariant with the buffers it guards. No behaviour change on the head path, which already filters n > 128 before calling in. Regression: a direct fvc_search on CompleteGraph[129] must return 0 with zero steps (test_vertex_coloring_internals). Without the guard it returns 129 via the lb >= ub short-circuit, so the assertion genuinely fails when the guard is absent. Verified: default build clean; graph_tests green (17 tests); make check-c99 and make check-packed-aware pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018GNB6E1ftx4TkAk47VfkNJ
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.
Summary
Closes RG-2 adversarial finding #2 (from PR #73):
fvc_searchis exported insrc/graph/graph.h, and its innerfvc_bbuses stack arrayschar seen[FVC_MAX_VERTICES + 2]/char forbid[FVC_MAX_VERTICES + 2], indexedup to
used + 1as the search deepens. The 128-vertex cap that keeps thoseindices in bounds was enforced only in the head
builtin_find_vertex_coloring,never in
fvc_search— and because the symbol is exported whileFVC_MAX_VERTICESis not, a cross-TU caller passingn > 128could not discoverthe precondition and would overflow the buffers.
Fix (one line + comment)
fvc_searchnow refuses (return 0) whenn > FVC_MAX_VERTICES, so theinvariant lives with the buffers it protects rather than in an untrusted caller.
return 0is the existing "cannot prove minimality, refuse" contract, so thehead leaves the expression unevaluated exactly as it already does for
n > 128.No behaviour change on the head path —
builtin_find_vertex_coloringalreadyfilters
n > 128before calling in, so every graph that reachesfvc_searchthrough the head has
n ≤ 128and is unaffected.Test
A regression assertion in
test_vertex_coloring_internals: a directfvc_searchonCompleteGraph[129]must return0with zero steps. Without theguard it returns
129via thelb >= ubshort-circuit, so the assertion failswhen the guard is absent — a genuine regression check, not a tautology.
Verification
-Werrorgate set).graph_testsgreen — 17 tests incl.test_vertex_coloring/test_vertex_coloring_internals(true exit 0, captured unpiped).make check-c99,make check-packed-awarepass.🤖 Generated with Claude Code
https://claude.ai/code/session_018GNB6E1ftx4TkAk47VfkNJ