Skip to content

Modeling Algorithms - ShapeUpgrade_UnifySameDomain: guard null pcurve dereferences#1392

Open
gsdali wants to merge 1 commit into
Open-Cascade-SAS:masterfrom
gsdali:fix/348-unifysamedomain-null-pcurve-guard
Open

Modeling Algorithms - ShapeUpgrade_UnifySameDomain: guard null pcurve dereferences#1392
gsdali wants to merge 1 commit into
Open-Cascade-SAS:masterfrom
gsdali:fix/348-unifysamedomain-null-pcurve-guard

Conversation

@gsdali

@gsdali gsdali commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Description of the change

Guards five unguarded BRep_Tool::CurveOnSurface(...) dereferences in
ShapeUpgrade_UnifySameDomain::IntUnifyFaces and its file-local SplitWire helper with
IsNull() checks, following the file's own established pattern used at every other
CurveOnSurface call site.

CurveOnSurface returns a null Handle(Geom2d_Curve) when an edge has no pcurve on the given
face — routine for a raw mesh-sewn solid (BRepBuilderAPI_Sewing output from an STL/mesh import)
at a vertex shared by more than two edges. The five sites dereference the result immediately
(->D1(...) / ->Value(...)) with no check, which is a null-pointer virtual call — a raw
SIGSEGV, uncatchable in-process (this is a memory-safety bug, not a Standard_Failure a caller
could try/catch).

  • A missing pcurve on a candidate edge now means "skip it, not a rankable direction" (continue).
  • A missing pcurve on the current edge (so there is nothing to compare candidates against) falls
    back to treating all candidates as equally likely — the same fallback the surrounding code
    already takes for the "only one candidate" case.

Related issue

Fixes #1391.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  1. Standalone repro: load the attached artifact, run ShapeUpgrade_UnifySameDomain::Build().
    Debug (-g -O0) single-TU override-link + lldb bt on stock master resolves the crash to
    ShapeUpgrade_UnifySameDomain.cxx:4003 (aPCurve->D1(...), null handle), reached via
    IntUnifyFacesUnifyFacesBuild.
  2. With the patch applied: the same artifact unifies successfully, run repeatedly with no crash.
  3. clang-format --dry-run --Werror is clean on every line this patch touches (two pre-existing
    formatting violations elsewhere in the file, both untouched by this patch, are unrelated
    pre-existing drift).

Reproducer artifact + standalone C++ driver:
https://github.com/SecondMouseAU/OCCTSwift/tree/main/Scripts/repro/348-unify-null-pcurve

Checklist:

  • My code follows the code style of this project
  • I have commented my code, particularly in hard-to-understand areas
  • My change requires a change to the documentation — N/A, no public API/behavior change beyond
    "does not crash"
  • I have added tests to cover my changes — regression coverage lives in the downstream Swift
    wrapper project (OCCTSwift) since this repo's DRAW test suite doesn't have an equivalent
    fixture-driven mesh-sew flow readily available; happy to add a DRAW test if maintainers
    point me at the right harness/fixture convention for this area

… dereferences

Fixes Open-Cascade-SAS#1391.

IntUnifyFaces (and its file-local SplitWire helper) disambiguate between
multiple candidate next-edges at a branching vertex by comparing each
candidate's pcurve tangent direction on the current reference face. Three
call sites in IntUnifyFaces (and the matching pair in SplitWire) fetched
that pcurve via BRep_Tool::CurveOnSurface and dereferenced it immediately
without checking IsNull() first, unlike every other CurveOnSurface call
site in this file. CurveOnSurface legitimately returns a null handle when
an edge has no pcurve on the given face -- the common case for a raw
mesh-sewn solid at a vertex shared by more than two edges -- so the
dereference is a null-pointer virtual call, uncatchable in-process.

Guard all five sites with IsNull() checks, following the file's own
established pattern: a missing pcurve on a *candidate* edge means "skip
it, not a rankable direction"; a missing pcurve on the *current* edge
(so nothing to compare against) falls back to treating all candidates as
equally likely, same as the existing single-candidate shortcut just
above it.

Verified against the attached artifact: builds successfully with the
patch (multiple runs), SIGSEGVs 100% of the time without it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

ShapeUpgrade_UnifySameDomain: unguarded null-pcurve dereference SIGSEGVs on mesh-sewn solids

1 participant