From 1ea54a0f56b0e7fcc4ada437b97f38e213714ea1 Mon Sep 17 00:00:00 2001 From: Luochenghuang Date: Fri, 29 May 2026 10:38:06 -0700 Subject: [PATCH] Fix dead-store in intersect_line_with_prism slist dedup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The duplicate-removal step at the end of intersect_line_with_prism wrote deduped values into a stack VLA slist_unique and then did 'slist = slist_unique;' before returning the new count. But slist is a pass-by-value pointer parameter, so this assignment only rebinds the local variable — the caller's buffer is never touched, and slist_unique is destroyed when the function returns. The caller then read the first num_unique_elements entries of the sorted-but-undeduped buffer rather than the actual deduped values. In intersect_line_segment_with_prism this corrupts the inside/outside parity walk: a near-duplicate that the dedup loop intended to drop remains in the buffer (producing a phantom thin 'inside' sliver of width ~1e-3*|s|), and a real far-end crossing is silently dropped because the caller stops at the smaller returned count. Worst case error is on the order of the prism diameter when an exit crossing is lost and parity inverts for the remainder of the segment. The bug only triggers when the qsort'd slist contains two values within 1e-3*|s| of each other, which happens for edge-grazing rays, rays through or near a shared vertex, and near-tangent rays where floating-point noise produces paired hits. test-prism's random-ray distribution does not statistically hit the 1e-3 window often enough to flag this in the existing comparison-vs-block tests, which is why the bug has lived in tree across PR #75 (which only changed slist sizing/fallback, not the dedup logic). Fix is one line: replace the dead pointer reassignment with a memcpy back into the caller's buffer. Algorithm, tolerance, and comparison semantics are all preserved — the dead store just becomes the write-back that the original code obviously intended. is already included; memcpy is used elsewhere in the file. --- utils/geom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/geom.c b/utils/geom.c index 9ed5999..4e37d7c 100644 --- a/utils/geom.c +++ b/utils/geom.c @@ -2231,7 +2231,7 @@ int intersect_line_with_prism(prism *prsm, vector3 pc, vector3 dc, double *slist num_unique_elements++; } } - slist = slist_unique; + memcpy(slist, slist_unique, num_unique_elements * sizeof(double)); num_intersections = num_unique_elements; return num_intersections; }