@@ -155,9 +155,14 @@ def match(c, snap):
155155# " #5 0x.. in _excinfo_clear_type /abs/path/Python/crossinterp.c:1319:15"
156156# The CPython source dir is matched anywhere in the absolute path; leading libc/pthread
157157# frames carry no such path and are skipped, as is fatal/dump plumbing (via _BT_SKIP).
158+ # The source path may be absolute (Clang builds: /home/.../Objects/foo.c:12:3) or relative
159+ # (GCC builds: Objects/foo.c:12, also no column). Make the absolute prefix and the column
160+ # optional so GCC-built crashes are parsed too -- otherwise extract_native_sites finds nothing
161+ # in the ASan trace and the dedup falls back to faulthandler's sparser (GCC-inlined) C-stack,
162+ # mislabelling known bugs as new (e.g. a whole OOM-0004 batch keyed on _Py_MergeZeroLocalRefcount).
158163_ASAN_FRAME = re .compile (
159- r"#\d+\s+0x[0-9a-fA-F]+\s+in\s+(\w+)\s+\S*?"
160- r"/ ((?:Objects|Python|Modules|Include|Parser)/[\w./+-]+\.(?:c|h)):(\d+)"
164+ r"#\d+\s+0x[0-9a-fA-F]+\s+in\s+(\w+)\s+(?: \S*?/) ?"
165+ r"((?:Objects|Python|Modules|Include|Parser)/[\w./+-]+\.(?:c|h)):(\d+)"
161166)
162167# fatal/assert/dump plumbing -- skip so a recorded frame is the real crash/assert site.
163168# The debug allocator's free-time checks (_PyMem_DebugCheckAddress / _PyMem_DebugRawFree /
@@ -173,6 +178,14 @@ def match(c, snap):
173178 r"|_Py_NegativeRefcount|_Py_DumpStack|faulthandler\w*"
174179 r"|_Py_DumpExtensionModules"
175180 r"|_PyMem_DebugCheckAddress|_PyMem_DebugRawFree|_PyMem_DebugFree"
181+ # The _testcapi set_nomemory injection hooks and the PyMem_/PyObject_ free/realloc
182+ # wrappers are pass-through allocator plumbing: when one is the innermost frame the real
183+ # defect is the CALLER doing the bad free (e.g. free_list_items = OOM-0004), so skip them
184+ # too. Without this, a double-free caught in the free hook resolves to hook_ffree/PyMem_Free
185+ # (not a catalog site) and the crash is mislabelled oomNEW -- notably on GCC builds, whose
186+ # ASan trace exposes these frames where Clang inlines them away.
187+ r"|hook_fmalloc|hook_fcalloc|hook_frealloc|hook_ffree"
188+ r"|PyMem_Free|PyMem_RawFree|PyObject_Free|PyMem_Realloc|PyMem_RawRealloc|PyObject_Realloc"
176189 r"|tracemalloc_(raw_)?(alloc|calloc|realloc|free))$"
177190)
178191# Inlined refcount/atomic helpers live in these headers and show up as the innermost frame
0 commit comments