From 892366e86d3292ef566f574e35aab5f6cdc33d6f Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Mon, 21 Sep 2026 09:45:57 +0700 Subject: [PATCH] The program the copy was written for is in both sweeps now bytes-copy.flan came in with the lane that made (bytes s) allocate, and it went into test_acceptance.ml and nowhere else. It is the one program in the corpus that takes a block from an allocator, writes through it immediately, and then takes another from an arena that is freed and destroyed under it -- which is the shape both opt-in sweeps exist for, and neither was running it. Both, not one, because the two tools answer different halves: a copy one byte short is a heap overflow ASan names, and a copy whose tail was never written is an uninitialised read only memcheck can see. Clean under both. --- test/test_sanitize.ml | 8 ++++++++ test/test_valgrind.ml | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/test/test_sanitize.ml b/test/test_sanitize.ml index b43cd72..2a4e481 100644 --- a/test/test_sanitize.ml +++ b/test/test_sanitize.ml @@ -118,6 +118,14 @@ let corpus = an output comparison does not. *) "programs/two-numbers.flan", []; "programs/bytes2.flan", []; + (* (bytes s) allocates a copy now rather than reinterpreting the string, + which is the one change in that lane this tool can see: the copy is a + block from an allocator, it is written through immediately, and the + last case takes its block from an arena that is then freed and + destroyed. A copy one byte short, or a write landing after the block, + is a heap overflow here and a correct-looking program everywhere + else. *) + "programs/bytes-copy.flan", []; "programs/cleanup.flan", []; "programs/conditions.flan", []; "programs/debug.flan", []; diff --git a/test/test_valgrind.ml b/test/test_valgrind.ml index 8631e71..672950b 100644 --- a/test/test_valgrind.ml +++ b/test/test_valgrind.ml @@ -198,6 +198,11 @@ let corpus = "programs/arena-value.flan", []; "programs/bounds.flan", [ "0" ]; "programs/bytes2.flan", []; + (* The same program [test_sanitize.ml] added, and here for the half that + one cannot answer: a copy whose tail was never written reads as a + perfectly addressable block to ASan and as an uninitialised value to + memcheck. *) + "programs/bytes-copy.flan", []; "programs/cleanup.flan", []; "programs/conditions.flan", []; "programs/debug.flan", [];