From 11f3e05d63d6d7a39d59f8edc9baf0ad9bd7438b Mon Sep 17 00:00:00 2001 From: Matthew Guthaus Date: Sat, 27 Jun 2026 12:30:57 -0700 Subject: [PATCH] syn: fix stack-use-after-return in constant fold sliceDff sliceDff() was declared to return a BundleView (a non-owning view) but returned the owning Bundle produced by Graph::add(). The implicit BundleView(const Bundle&) conversion stores a pointer to that temporary, which is destroyed when sliceDff() returns, so foldSequentials() then indexes a dangling view (BundleView::operator[] -> Bundle::operator[]). This is undefined behavior that optimized builds tolerate (sliceDff() is inlined, so the temporary's storage survives the read), but a DEBUG (unoptimized) build faults on. It reproduces as a SIGSEGV during synthesis of larger designs using the integrated syn flow (e.g. asap7/aes, asap7/jpeg with SYNTH_USE_SYN=1); AddressSanitizer reports a stack-use-after-return at ir/Bundle.cc. Return an owning Bundle from sliceDff() and hold it as a Bundle at the call site (a BundleView local would re-create the dangle). Signed-off-by: Matthew Guthaus --- src/syn/src/flow/constant_fold.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/syn/src/flow/constant_fold.cc b/src/syn/src/flow/constant_fold.cc index 66567551d74..10c9de79954 100644 --- a/src/syn/src/flow/constant_fold.cc +++ b/src/syn/src/flow/constant_fold.cc @@ -448,10 +448,10 @@ static void foldCombinationals(Graph& g) }); } -static BundleView sliceDff(Graph& g, - const Dff* original, - uint32_t base, - uint32_t width) +static Bundle sliceDff(Graph& g, + const Dff* original, + uint32_t base, + uint32_t width) { assert(width > 0); @@ -575,7 +575,7 @@ static bool foldSequentials(Graph& g) break; } } - BundleView new_out_slice = sliceDff(g, dff, i, slice_width); + Bundle new_out_slice = sliceDff(g, dff, i, slice_width); for (uint32_t k = 0; k < slice_width; k++) { new_out[i + k] = new_out_slice[k]; }