[mis] validate an input graph with more constraints - #313
Merged
Conversation
readECLgraph only bounded the neighbor list from above. Both operands of that comparison are signed, so a negative entry was accepted and used directly as an index into the nodes-sized nstat allocation, which compute-sanitizer reports as an invalid __global__ read in the findmins kernel. Reject negative entries. Two further crafted inputs make findmins spin forever rather than read out of bounds: a self loop leaves a node unable to beat itself, and an edge stored in only one direction leaves a node waiting on a neighbor that never clears it. Add verifyUndirectedECLgraph for the checks that only hold for undirected graphs and call it from the mis programs. It is deliberately not part of readECLgraph because floydwarshall2 runs on a directed graph. Also compute the allocation and read sizes in size_t so that nodes + 1 cannot overflow, and close the input file on the error paths. Co-authored-by: Cursor <cursoragent@cursor.com>
Reject malformed graph structures before connected-components and graph-coloring kernels run. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Pull request overview
Strengthens ECL graph loading and prevents invalid graph structures from causing out-of-bounds access or nontermination.
Changes:
- Validates neighbor indices and safely computes allocation/read sizes.
- Adds undirected, loop-free, sorted adjacency validation.
- Applies validation across MIS, graph-coloring, and connected-components benchmarks.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/mis-cuda/graph.h |
Adds robust loading and graph validation. |
src/mis-cuda/main.cu |
Validates CUDA MIS input. |
src/mis-sycl/main.cpp |
Validates SYCL MIS input. |
src/mis-hip/main.cu |
Validates HIP MIS input. |
src/mis-omp/main.cpp |
Validates OpenMP MIS input. |
src/gc-cuda/main.cu |
Validates CUDA GC input. |
src/gc-sycl/main.cpp |
Validates SYCL GC input. |
src/gc-hip/main.cu |
Validates HIP GC input. |
src/gc-omp/main.cpp |
Validates OpenMP GC input. |
src/cc-cuda/main.cu |
Validates CUDA CC input. |
src/cc-sycl/main.cpp |
Validates SYCL CC input. |
src/cc-hip/main.cu |
Validates HIP CC input. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Fixes #312.
Problem
readECLgraphbounded the neighbor list only from above:g.nlistisint*andg.nodesisint, so this is a signed comparison and a negative entry passes it.findminsthen uses the value directly innstat[nlist[i]], wherenstat_disnodes * sizeof(stattype)bytes withstattypebeingunsigned char, so the read lands below the allocation. Reproduced with the reporter's PoC:While fixing that I found two more crafted graphs that pass every existing check and make
findminsloop forever instead of reading out of bounds. Both were still running when a 20 s timeout killed them, against 0.12 s forinternet.egr:nodes=2, nindex=[0,1,2], nlist=[0,1]— each node is its own neighbor, so neithernv > nstat[v]nornv == nstat[v] && v > vholds and the node can never beat itself.nodes=2, nindex=[0,1,1], nlist=[1]— the edge is stored in one direction only, so the neighbor never runs thenstat[nlist[i]] = outwrite that would clear the waiting node's low bit.Changes
verifyUndirectedECLgraph, which rejects self loops, unsorted or duplicated neighbor lists, and edges missing their reverse direction, and call it frommis-cuda,mis-sycl,mis-hip, andmis-omp.size_tsog.nodes + 1cannot overflow, andfclosethe input on the error paths.verifyUndirectedECLgraphis deliberately not part ofreadECLgraph.src/mis-cuda/graph.his shared via-I../mis-cudawithcc-*,gc-*, andfloydwarshall2-*, andfloydwarshall2's own inputCollegeMsg.egris a directed graph, so requiring symmetry in the reader would break it. The symmetry test uses bisection over each neighbor list, which is why sortedness is checked first.Testing
Verified on an NVIDIA Tesla M40 with CUDA 12.1, and with the oneAPI DPC++ SYCL compiler targeting the same GPU.
All four bad inputs are now rejected at load time by both
mis-cudaandmis-sycl:mis-cuda ./internet.egr 1still passes under bothcompute-sanitizer --tool=memcheckand--tool=initcheckwithERROR SUMMARY: 0 errors.No regressions in the benchmarks sharing the header:
cc-cudaonamazon0601.egrreportsPASS,gc-cudacolors the same graph, andfloydwarshall2-cudaon the directedCollegeMsg.egrstill reportsresults match. I also confirmed thatinternet.egr,amazon0601.egr,soc-LiveJournal1.egr, andCollegeMsg.egrare all free of self loops and have strictly sorted neighbor lists, so the new checks reject none of the in-tree inputs.mis-hipandmis-ompwere syntax checked only, as this machine has no AMD GPU and the OpenMP offload Makefile needsicpx.