Skip to content

Fix tutor2pp segfault from double-free in createObjects - #1426

Open
mchamberland wants to merge 1 commit into
nrc-cnrc:developfrom
mchamberland:fix/tutor2pp-createobjects-double-free
Open

Fix tutor2pp segfault from double-free in createObjects#1426
mchamberland wants to merge 1 commit into
nrc-cnrc:developfrom
mchamberland:fix/tutor2pp-createobjects-double-free

Conversation

@mchamberland

Copy link
Copy Markdown
Contributor

Summary

  • Fix a segmentation fault in tutor2pp (and any user code derived from EGS_SimpleApplication) caused by a double-free in EGS_ObjectFactory::createObjects().
  • createObjects() now deletes its working EGS_Input pointer only when it extracted the section itself via takeInputItem(), matching the ownership pattern already used in EGS_BaseGeometry::createGeometry().

Fixes #1140

Root cause

EGS_SimpleApplication takes the source definition block from the input file, passes that pointer to EGS_BaseSource::createSource(), and then deletes it. Inside createSource()createObjects(), when the argument is already a source definition section, the local input pointer aliases the caller's pointer. An unconditional delete input at the end of createObjects() (added in def34e2 to fix a sanitizer-reported leak) freed memory that EGS_SimpleApplication then deleted again.

Advanced applications (EGS_AdvancedApplication, egs_brachy, tutor7pp, etc.) were unaffected because they pass the full input file; createObjects() takes the section internally and owns that extracted pointer.

Reasoning / alignment with #1140

Ernesto Mainegra identified the same cause on #1140 and suggested two approaches:

  1. Pass a copy into createObjects so the factory frees its copy while the caller keeps the original.
  2. Adjust deletion in egs_simple_application.cpp (Matt Inglis Whalen's workaround was to remove delete source_input entirely).

This PR follows option 1 in intent—make ownership explicit at the factory—without copying EGS_Input. When the caller passes an already-extracted section, createObjects() leaves it for the caller to delete; when it extracts the section from a larger input (the advanced-application path), it deletes what it took. That preserves the 2021 leak fix for the advanced path while fixing the SimpleApplication double-free, and avoids the leak that would result from simply removing delete source_input in egs_simple_application.cpp.

Test plan

  • Rebuild libegspp and run tutor2pp -i test1.egsinp -p tutor_data on macOS (eb-dev config): completes with deposited/transmitted energy fractions.
  • CI / upstream reviewer: confirm tutor2pp and an EGS_AdvancedApplication example still run on Linux.

Made with Cursor

createObjects() always deleted its local input pointer, but when the
caller already passed a section block (as EGS_SimpleApplication does
for source definition), the caller deleted the same pointer again.
Only delete the input when createObjects extracted the section via
takeInputItem(), matching the ownership pattern already used in
createGeometry().

Fixes nrc-cnrc#1140

Co-authored-by: Cursor <cursoragent@cursor.com>
@mchamberland
mchamberland requested a review from a team as a code owner June 27, 2026 23:10
@rtownson rtownson self-assigned this Jun 29, 2026
@rtownson rtownson added the bug label Jun 29, 2026
@ftessier ftessier added this to the Release 2027 milestone Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants