Skip to content

Fix stack-use-after-scope ASAN error#192

Merged
knoepfel merged 1 commit intoFramework-R-D:mainfrom
knoepfel:fix-memory-error
Dec 17, 2025
Merged

Fix stack-use-after-scope ASAN error#192
knoepfel merged 1 commit intoFramework-R-D:mainfrom
knoepfel:fix-memory-error

Conversation

@knoepfel
Copy link
Copy Markdown
Member

@knoepfel knoepfel commented Dec 16, 2025

The to_product_specifications(std::string const&, ...) function was being invoked with a temporary object, and that temporary object was being unsafely cached by reference via the to_product_specification helper struct. This PR removes the to_product_specification helper struct, and strings passed to the to_product_specifications(...) function are now passed by value.


Error fixed by this PR:

37: ==87556==ERROR: AddressSanitizer: stack-use-after-scope on address 0x00016d9f6c77 at pc 0x000102723580 bp 0x00016d9f6a50 sp 0x00016d9f6a48                                                                                                                            
37: READ of size 1 at 0x00016d9f6c77 thread T0                                                                                                                                                                                                                            
37:     #0 0x00010272357c in phlex::experimental::to_product_specification::operator()(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, phlex::experimental::type_id) const product_specification.hpp:48                      
37:     #1 0x0001027227e8 in phlex::experimental::to_product_specifications(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, s
td::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>, std::__1::vector<phlex::experimental::type_id, std::__1::allocator<phlex::experimental::type_id>>) product_specification.cpp:74                                
37:     #2 0x0001073188d0 in phlex::experimental::transform_node<phlex::experimental::algorithm_bits<std::__1::function<int (phlex::experimental::data_cell_index const&)>, int (*)(phlex::experimental::data_cell_index const&)>>::transform_node(phlex::experimental::al
gorithm_name, unsigned long, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>, tbb::detail::d2::graph&, p
hlex::experimental::algorithm_bits<std::__1::function<int (phlex::experimental::data_cell_index const&)>, int (*)(phlex::experimental::data_cell_index const&)>, std::__1::vector<phlex::experimental::product_query, std::__1::allocator<phlex::experimental::product_que
ry>>, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>) declared_transform.hpp:85
37:     #3 0x00010731819c in std::__1::unique_ptr<phlex::experimental::transform_node<phlex::experimental::algorithm_bits<std::__1::function<int (phlex::experimental::data_cell_index const&)>, int (*)(phlex::experimental::data_cell_index const&)>>, std::__1::default
_delete<phlex::experimental::transform_node<phlex::experimental::algorithm_bits<std::__1::function<int (phlex::experimental::data_cell_index const&)>, int (*)(phlex::experimental::data_cell_index const&)>>>> std::__1::make_unique[abi:ne200100]<phlex::experimental::t
ransform_node<phlex::experimental::algorithm_bits<std::__1::function<int (phlex::experimental::data_cell_index const&)>, int (*)(phlex::experimental::data_cell_index const&)>>, phlex::experimental::algorithm_name, unsigned long&, std::__1::vector<std::__1::basic_str
ing<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>, tbb::detail::d2::graph&, phlex::experimental::algorithm_bits<std::__1::function<int (phlex:
:experimental::data_cell_index const&)>, int (*)(phlex::experimental::data_cell_index const&)>, std::__1::vector<phlex::experimental::product_query, std::__1::allocator<phlex::experimental::product_query>>, std::__1::vector<std::__1::basic_string<char, std::__1::cha
r_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>, 0>(phlex::experimental::algorithm_name&&, unsigned long&, std::__1::vector<std::__1::basic_string<char, std::__1::
char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>&&, tbb::detail::d2::graph&, phlex::experimental::algorithm_bits<std::__1::function<int (phlex::experimental::dat
a_cell_index const&)>, int (*)(phlex::experimental::data_cell_index const&)>&&, std::__1::vector<phlex::experimental::product_query, std::__1::allocator<phlex::experimental::product_query>>&&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>
, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>&&) unique_ptr.h:767
37:     #4 0x000107317ce0 in auto phlex::experimental::registration_api<phlex::experimental::transform_node, phlex::experimental::algorithm_bits<std::__1::function<int (phlex::experimental::data_cell_index const&)>, int (*)(phlex::experimental::data_cell_index const
&)>>::input_family(std::__1::array<phlex::experimental::product_query, 1ul>)::'lambda'(auto, auto)::operator()<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std
::__1::char_traits<char>, std::__1::allocator<char>>>>, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>>
(auto, auto) const registration_api.hpp:67                                                                                          
37:     #5 0x000107317a08 in std::__1::unique_ptr<phlex::experimental::declared_transform, std::__1::default_delete<phlex::experimental::declared_transform>> std::__1::__invoke_void_return_wrapper<std::__1::unique_ptr<phlex::experimental::declared_transform, std::__
1::default_delete<phlex::experimental::declared_transform>>, false>::__call[abi:ne200100]<phlex::experimental::registration_api<phlex::experimental::transform_node, phlex::experimental::algorithm_bits<std::__1::function<int (phlex::experimental::data_cell_index cons
t&)>, int (*)(phlex::experimental::data_cell_index const&)>>::input_family(std::__1::array<phlex::experimental::product_query, 1ul>)::'lambda'(auto, auto)&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::_
_1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::ch
ar_traits<char>, std::__1::allocator<char>>>>>(phlex::experimental::registration_api<phlex::experimental::transform_node, phlex::experimental::algorithm_bits<std::__1::function<int (phlex::experimental::data_cell_index const&)>, int (*)(phlex::experimental::data_cel
l_index const&)>>::input_family(std::__1::array<phlex::experimental::product_query, 1ul>)::'lambda'(auto, auto)&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, 
std::__1::char_traits<char>, std::__1::allocator<char>>>>&&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char
>>>>&&) invoke.h:243                                                                                                                
37:     #6 0x00010733bbb4 in phlex::experimental::registrar<std::__1::unique_ptr<phlex::experimental::declared_transform, std::__1::default_delete<phlex::experimental::declared_transform>>>::create_node(std::__1::vector<std::__1::basic_string<char, std::__1::char_tr
aits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>) registrar.hpp:111
37:     #7 0x00010733cdd4 in void phlex::experimental::upstream_predicates<std::__1::unique_ptr<phlex::experimental::declared_transform, std::__1::default_delete<phlex::experimental::declared_transform>>, 1ul>::output_products<1ul>(std::__1::array<std::__1::basic_st
ring<char, std::__1::char_traits<char>, std::__1::allocator<char>>, 1ul>) upstream_predicates.hpp:47                                
37:     #8 0x0001073137f8 in create(phlex::experimental::graph_proxy<phlex::experimental::void_tag>&, phlex::experimental::configuration const&) last_index.cpp:14
37:     #9 0x0001025004f8 in phlex::experimental::load_module(phlex::experimental::framework_graph&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, boost::json::object) load_module.cpp:57
37:     #10 0x00010250e8a8 in phlex::experimental::run(boost::json::object const&, int) run.cpp:14                                  
37:     #11 0x0001024093f4 in main phlex.cpp:95                                                                                     
37:     #12 0x00018cb52b94 in start+0x17b8 (dyld:arm64e+0xfffffffffff3ab94)                                                          
37:                                                                                                                                 
37: Address 0x00016d9f6c77 is located in stack of thread T0 at offset 87 in frame                                                   
37:     #0 0x00010272241c in phlex::experimental::to_product_specifications(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>,
 std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>, std::__1::vector<phlex::experimental::type_id, std::__1::allocator<phlex::experimental::type_id>>) product_specification.cpp:66
37:                                                                                                                                 
37:   This frame has 5 object(s):                                                                                                   
37:     [32, 40) 'make_product_specification' (line 71)                                                                             
37:     [64, 120) 'ref.tmp' (line 71) <== Memory access at offset 87 is inside this variable                                        
37:     [160, 184) 'agg.tmp'                                                                                                        
37:     [224, 344) 'ref.tmp20' (line 74)                                                                                            
37:     [384, 424) 'agg.tmp24'                                                                                                      
37: HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork                
37:       (longjmp and C++ exceptions *are* supported)                                                                              
37: SUMMARY: AddressSanitizer: stack-use-after-scope product_specification.hpp:48 in phlex::experimental::to_product_specification::operator()(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, phlex::experimental::type_id) 
const

@codecov
Copy link
Copy Markdown

codecov bot commented Dec 16, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

@@            Coverage Diff             @@
##             main     #192      +/-   ##
==========================================
- Coverage   81.61%   81.44%   -0.17%     
==========================================
  Files         117      117              
  Lines        2099     2096       -3     
  Branches      332      332              
==========================================
- Hits         1713     1707       -6     
+ Misses        254      252       -2     
- Partials      132      137       +5     
Flag Coverage Δ
unittests 81.44% <100.00%> (-0.17%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
phlex/model/product_specification.cpp 92.00% <100.00%> (-0.31%) ⬇️
phlex/model/product_specification.hpp 66.66% <ø> (-8.34%) ⬇️

... and 5 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update beaa933...f65f413. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@beojan beojan self-requested a review December 17, 2025 16:48
Copy link
Copy Markdown
Contributor

@beojan beojan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@knoepfel knoepfel merged commit 57dcdf2 into Framework-R-D:main Dec 17, 2025
36 checks passed
@knoepfel knoepfel deleted the fix-memory-error branch December 17, 2025 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants