Monthly Summary: Fix Mismatched Deallocation Functions (May 2026)
Overview
Tristan Partin proposed a mechanical refactor to fix allocator/deallocator mismatches in PostgreSQL's frontend code, using a Coccinelle semantic patch. The goal is to enforce consistent pairing between the two parallel allocator families (pg_malloc/pg_free and palloc/pfree) in frontend builds, enabling future adoption of GCC's __attribute__((malloc(deallocator))) for compile-time enforcement. The first substantive review from Zsolt Parragi challenged both the completeness of the Coccinelle output and the overall methodology.
Problem Statement
PostgreSQL frontend code has two allocator families — pg_* (native frontend wrappers) and p* (shims for backend/frontend shared code) — both ultimately calling libc malloc/free. Mismatches between families (e.g., pnstrdup() + free()) are functionally harmless today but:
- Block
__attribute__((malloc(deallocator)))adoption, which would enable-Wmismatched-deallocwarnings and improve static analysis - Create cognitive overhead during code review (cannot reason locally about ownership)
- Are fragile if frontend
p*wrappers ever gain real behavior (debug instrumentation, minimal context allocator)
Proposed Approach
A Coccinelle .cocci script mechanically rewrites deallocator calls to match their corresponding allocator family. Run with --allow-inconsistent-paths, the script produces a large diff across src/fe_utils, src/bin, libpq, etc. The approach is reproducible and declarative.
First Review: Completeness and Strategy Challenged
Zsolt Parragi identified concrete deficiencies:
Missed rewrites
pg_malloc_arraymacro calls not recognized by the.coccirules (syntactic mismatch)- Cast expressions and out-parameter assignments defeating the pattern matcher
- Cross-function allocation (e.g.,
parse_identifierallocating into an out-parameter freed elsewhere) invisible to intra-procedural analysis
Internal inconsistency
- In
strtokx(src/fe_utils/stringutils.c), the patch rewritesfree()on line 96 but leaves a structurally identicalfree()on line 73 untouched — a direct artifact of--allow-inconsistent-paths
Methodological counter-proposal: attributes-first
Zsolt proposes inverting the workflow:
- Add
__attribute__((malloc(deallocator)))annotations first - Let the compiler/clang-tidy flag every mismatch automatically
- Fix mismatches guided by compiler output (possibly with clang-tidy auto-fix)
The argument: Coccinelle is inherently intra-procedural and syntactic, so it cannot achieve completeness for the cross-TU ownership patterns that exist in the codebase. Attributes propagate ownership through function signatures and enable tools that can reason inter-procedurally.
Current Status
The patch is stalled pending response from Tristan to the review feedback. Two concrete issues must be resolved:
- The specific missed sites and inconsistencies in the current diff
- The strategic question of whether Coccinelle-first or attributes-first is the correct ordering
No committer has weighed in yet.