agora inbox for [email protected]
help / color / mirror / Atom feed[PATCH v14 6/7] Restructure TupleTableSlot to allow tuples other than HeapTuple
114+ messages / 2 participants
[nested] [flat]
* [PATCH v14 6/7] Restructure TupleTableSlot to allow tuples other than HeapTuple
@ 2018-11-13 20:58 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2018-11-13 20:58 UTC (permalink / raw)
Author: Andres Freund and Ashutosh Bapat, with changes by Amit Khandekar
Discussion: https://postgr.es/m/[email protected]
---
src/backend/access/common/heaptuple.c | 184 +--
src/backend/catalog/index.c | 4 +-
src/backend/executor/execCurrent.c | 18 +-
src/backend/executor/execExpr.c | 5 +-
src/backend/executor/execExprInterp.c | 13 +-
src/backend/executor/execGrouping.c | 5 +-
src/backend/executor/execReplication.c | 41 +-
src/backend/executor/execScan.c | 4 +-
src/backend/executor/execTuples.c | 1665 ++++++++++++++++--------
src/backend/executor/nodeAgg.c | 5 +-
src/backend/executor/nodeHashjoin.c | 17 +-
src/backend/executor/nodeModifyTable.c | 13 +
src/backend/executor/nodeSubplan.c | 1 +
src/backend/jit/llvm/llvmjit.c | 8 +-
src/backend/jit/llvm/llvmjit_deform.c | 52 +-
src/backend/jit/llvm/llvmjit_expr.c | 3 +-
src/backend/jit/llvm/llvmjit_types.c | 4 +-
src/include/access/htup_details.h | 2 -
src/include/executor/executor.h | 1 +
src/include/executor/tuptable.h | 305 ++++-
src/include/jit/llvmjit.h | 7 +-
src/include/nodes/execnodes.h | 1 +
22 files changed, 1562 insertions(+), 796 deletions(-)
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 28127b311f5..ccb69bdd616 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -71,6 +71,8 @@
#define VARLENA_ATT_IS_PACKABLE(att) \
((att)->attstorage != 'p')
+static Datum getmissingattr(TupleDesc tupleDesc, int attnum, bool *isnull);
+
/* ----------------------------------------------------------------
* misc support routines
@@ -80,7 +82,7 @@
/*
* Return the missing value of an attribute, or NULL if there isn't one.
*/
-Datum
+static Datum
getmissingattr(TupleDesc tupleDesc,
int attnum, bool *isnull)
{
@@ -1350,186 +1352,6 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
values[attnum] = getmissingattr(tupleDesc, attnum + 1, &isnull[attnum]);
}
-/*
- * slot_deform_tuple
- * Given a TupleTableSlot, extract data from the slot's physical tuple
- * into its Datum/isnull arrays. Data is extracted up through the
- * natts'th column (caller must ensure this is a legal column number).
- *
- * This is essentially an incremental version of heap_deform_tuple:
- * on each call we extract attributes up to the one needed, without
- * re-computing information about previously extracted attributes.
- * slot->tts_nvalid is the number of attributes already extracted.
- */
-void
-slot_deform_tuple(TupleTableSlot *slot, int natts)
-{
- HeapTuple tuple = slot->tts_tuple;
- TupleDesc tupleDesc = slot->tts_tupleDescriptor;
- Datum *values = slot->tts_values;
- bool *isnull = slot->tts_isnull;
- HeapTupleHeader tup = tuple->t_data;
- bool hasnulls = HeapTupleHasNulls(tuple);
- int attnum;
- char *tp; /* ptr to tuple data */
- uint32 off; /* offset in tuple data */
- bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
- bool slow; /* can we use/set attcacheoff? */
-
- /*
- * Check whether the first call for this tuple, and initialize or restore
- * loop state.
- */
- attnum = slot->tts_nvalid;
- if (attnum == 0)
- {
- /* Start from the first attribute */
- off = 0;
- slow = false;
- }
- else
- {
- /* Restore state from previous execution */
- off = slot->tts_off;
- slow = TTS_SLOW(slot);
- }
-
- tp = (char *) tup + tup->t_hoff;
-
- for (; attnum < natts; attnum++)
- {
- Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum);
-
- if (hasnulls && att_isnull(attnum, bp))
- {
- values[attnum] = (Datum) 0;
- isnull[attnum] = true;
- slow = true; /* can't use attcacheoff anymore */
- continue;
- }
-
- isnull[attnum] = false;
-
- if (!slow && thisatt->attcacheoff >= 0)
- off = thisatt->attcacheoff;
- else if (thisatt->attlen == -1)
- {
- /*
- * We can only cache the offset for a varlena attribute if the
- * offset is already suitably aligned, so that there would be no
- * pad bytes in any case: then the offset will be valid for either
- * an aligned or unaligned value.
- */
- if (!slow &&
- off == att_align_nominal(off, thisatt->attalign))
- thisatt->attcacheoff = off;
- else
- {
- off = att_align_pointer(off, thisatt->attalign, -1,
- tp + off);
- slow = true;
- }
- }
- else
- {
- /* not varlena, so safe to use att_align_nominal */
- off = att_align_nominal(off, thisatt->attalign);
-
- if (!slow)
- thisatt->attcacheoff = off;
- }
-
- values[attnum] = fetchatt(thisatt, tp + off);
-
- off = att_addlength_pointer(off, thisatt->attlen, tp + off);
-
- if (thisatt->attlen <= 0)
- slow = true; /* can't use attcacheoff anymore */
- }
-
- /*
- * Save state for next execution
- */
- slot->tts_nvalid = attnum;
- slot->tts_off = off;
- if (slow)
- slot->tts_flags |= TTS_FLAG_SLOW;
- else
- slot->tts_flags &= ~TTS_FLAG_SLOW;
-}
-
-/*
- * slot_attisnull
- * Detect whether an attribute of the slot is null, without
- * actually fetching it.
- */
-bool
-slot_attisnull(TupleTableSlot *slot, int attnum)
-{
- HeapTuple tuple = slot->tts_tuple;
- TupleDesc tupleDesc = slot->tts_tupleDescriptor;
-
- /*
- * system attributes are handled by heap_attisnull
- */
- if (attnum <= 0)
- {
- if (tuple == NULL) /* internal error */
- elog(ERROR, "cannot extract system attribute from virtual tuple");
- if (tuple == &(slot->tts_minhdr)) /* internal error */
- elog(ERROR, "cannot extract system attribute from minimal tuple");
- return heap_attisnull(tuple, attnum, tupleDesc);
- }
-
- /*
- * fast path if desired attribute already cached
- */
- if (attnum <= slot->tts_nvalid)
- return slot->tts_isnull[attnum - 1];
-
- /*
- * return NULL if attnum is out of range according to the tupdesc
- */
- if (attnum > tupleDesc->natts)
- return true;
-
- /*
- * otherwise we had better have a physical tuple (tts_nvalid should equal
- * natts in all virtual-tuple cases)
- */
- if (tuple == NULL) /* internal error */
- elog(ERROR, "cannot extract attribute from empty tuple slot");
-
- /* and let the tuple tell it */
- return heap_attisnull(tuple, attnum, tupleDesc);
-}
-
-/*
- * slot_getsysattr
- * This function fetches a system attribute of the slot's current tuple.
- * Unlike slot_getattr, if the slot does not contain system attributes,
- * this will return false (with a NULL attribute value) instead of
- * throwing an error.
- */
-bool
-slot_getsysattr(TupleTableSlot *slot, int attnum,
- Datum *value, bool *isnull)
-{
- HeapTuple tuple = slot->tts_tuple;
-
- Assert(attnum < 0); /* else caller error */
- if (tuple == NULL ||
- tuple == &(slot->tts_minhdr))
- {
- /* No physical tuple, or minimal tuple, so fail */
- *value = (Datum) 0;
- *isnull = true;
- return false;
- }
- *value = heap_getsysattr(tuple, attnum, slot->tts_tupleDescriptor, isnull);
- return true;
-}
-
/*
* heap_freetuple
*/
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 21bdf794da6..a980202a7b1 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2041,7 +2041,9 @@ FormIndexDatum(IndexInfo *indexInfo,
Datum iDatum;
bool isNull;
- if (keycol != 0)
+ if (keycol < 0)
+ iDatum = slot_getsysattr(slot, keycol, &isNull);
+ else if (keycol != 0)
{
/*
* Plain index column; get the value we need directly from the
diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c
index aadf7493827..39c462a4e59 100644
--- a/src/backend/executor/execCurrent.c
+++ b/src/backend/executor/execCurrent.c
@@ -218,27 +218,25 @@ execCurrentOf(CurrentOfExpr *cexpr,
ItemPointer tuple_tid;
#ifdef USE_ASSERT_CHECKING
- if (!slot_getsysattr(scanstate->ss_ScanTupleSlot,
- TableOidAttributeNumber,
- &ldatum,
- &lisnull))
+ ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
+ TableOidAttributeNumber,
+ &lisnull);
+ if (lisnull)
ereport(ERROR,
(errcode(ERRCODE_INVALID_CURSOR_STATE),
errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
cursor_name, table_name)));
- Assert(!lisnull);
Assert(DatumGetObjectId(ldatum) == table_oid);
#endif
- if (!slot_getsysattr(scanstate->ss_ScanTupleSlot,
- SelfItemPointerAttributeNumber,
- &ldatum,
- &lisnull))
+ ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
+ SelfItemPointerAttributeNumber,
+ &lisnull);
+ if (lisnull)
ereport(ERROR,
(errcode(ERRCODE_INVALID_CURSOR_STATE),
errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
cursor_name, table_name)));
- Assert(!lisnull);
tuple_tid = (ItemPointer) DatumGetPointer(ldatum);
*current_tid = *tuple_tid;
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index a4099c23176..914d04186bd 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -3313,6 +3313,7 @@ ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
*/
ExprState *
ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
+ const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
int numCols,
AttrNumber *keyColIdx,
Oid *eqfunctions,
@@ -3354,7 +3355,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
scratch.d.fetch.last_var = maxatt;
scratch.d.fetch.fixed = false;
scratch.d.fetch.known_desc = ldesc;
- scratch.d.fetch.kind = NULL;
+ scratch.d.fetch.kind = lops;
ExecComputeSlotInfo(state, &scratch);
ExprEvalPushStep(state, &scratch);
@@ -3362,7 +3363,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
scratch.d.fetch.last_var = maxatt;
scratch.d.fetch.fixed = false;
scratch.d.fetch.known_desc = rdesc;
- scratch.d.fetch.kind = NULL;
+ scratch.d.fetch.kind = rops;
ExecComputeSlotInfo(state, &scratch);
ExprEvalPushStep(state, &scratch);
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 357eae41cc3..dbf2445a21d 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -428,7 +428,6 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
{
CheckOpSlotCompatibility(op, innerslot);
- /* XXX: worthwhile to check tts_nvalid inline first? */
slot_getsomeattrs(innerslot, op->d.fetch.last_var);
EEO_NEXT();
@@ -4026,15 +4025,15 @@ void
ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
TupleTableSlot *slot)
{
- bool success;
+ Datum d;
/* slot_getsysattr has sufficient defenses against bad attnums */
- success = slot_getsysattr(slot,
- op->d.var.attnum,
- op->resvalue,
- op->resnull);
+ d = slot_getsysattr(slot,
+ op->d.var.attnum,
+ op->resnull);
+ *op->resvalue = d;
/* this ought to be unreachable, but it's cheap enough to check */
- if (unlikely(!success))
+ if (unlikely(*op->resnull))
elog(ERROR, "failed to fetch attribute from slot");
}
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 5bc200e4dc3..abce1e95cb6 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -75,7 +75,8 @@ execTuplesMatchPrepare(TupleDesc desc,
eqFunctions[i] = get_opcode(eqOperators[i]);
/* build actual expression */
- expr = ExecBuildGroupingEqual(desc, desc, numCols, keyColIdx, eqFunctions,
+ expr = ExecBuildGroupingEqual(desc, desc, NULL, NULL,
+ numCols, keyColIdx, eqFunctions,
parent);
return expr;
@@ -206,7 +207,9 @@ BuildTupleHashTable(PlanState *parent,
&TTSOpsMinimalTuple);
/* build comparator for all columns */
+ /* XXX: should we support non-minimal tuples for the inputslot? */
hashtable->tab_eq_func = ExecBuildGroupingEqual(inputDesc, inputDesc,
+ &TTSOpsMinimalTuple, &TTSOpsMinimalTuple,
numCols,
keyColIdx, eqfuncoids,
parent);
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index 071ba8762d4..727770eab56 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -170,8 +170,11 @@ retry:
HeapUpdateFailureData hufd;
HTSU_Result res;
HeapTupleData locktup;
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)outslot;
- ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self);
+ /* Only a heap tuple has item pointers. */
+ Assert(TTS_IS_HEAPTUPLE(outslot) || TTS_IS_BUFFERTUPLE(outslot));
+ ItemPointerCopy(&hslot->tuple->t_self, &locktup.t_self);
PushActiveSnapshot(GetLatestSnapshot());
@@ -334,8 +337,12 @@ retry:
HeapUpdateFailureData hufd;
HTSU_Result res;
HeapTupleData locktup;
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)outslot;
- ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self);
+ /* Only a heap tuple has item pointers. */
+ Assert(TTS_IS_HEAPTUPLE(outslot) || TTS_IS_BUFFERTUPLE(outslot));
+
+ ItemPointerCopy(&hslot->tuple->t_self, &locktup.t_self);
PushActiveSnapshot(GetLatestSnapshot());
@@ -456,6 +463,12 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
HeapTuple tuple;
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
Relation rel = resultRelInfo->ri_RelationDesc;
+ HeapTupleTableSlot *hsearchslot = (HeapTupleTableSlot *)searchslot;
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)slot;
+
+ /* We expect both searchslot and the slot to contain a heap tuple. */
+ Assert(TTS_IS_HEAPTUPLE(searchslot) || TTS_IS_BUFFERTUPLE(searchslot));
+ Assert(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot));
/* For now we support only tables. */
Assert(rel->rd_rel->relkind == RELKIND_RELATION);
@@ -467,8 +480,7 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
resultRelInfo->ri_TrigDesc->trig_update_before_row)
{
slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
- &searchslot->tts_tuple->t_self,
- NULL, slot);
+ &hsearchslot->tuple->t_self, NULL, slot);
if (slot == NULL) /* "do nothing" */
skip_tuple = true;
@@ -488,19 +500,18 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
/* OK, update the tuple and index entries for it */
- simple_heap_update(rel, &searchslot->tts_tuple->t_self,
- slot->tts_tuple);
+ simple_heap_update(rel, &hsearchslot->tuple->t_self, hslot->tuple);
if (resultRelInfo->ri_NumIndices > 0 &&
- !HeapTupleIsHeapOnly(slot->tts_tuple))
+ !HeapTupleIsHeapOnly(hslot->tuple))
recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
estate, false, NULL,
NIL);
/* AFTER ROW UPDATE Triggers */
ExecARUpdateTriggers(estate, resultRelInfo,
- &searchslot->tts_tuple->t_self,
- NULL, tuple, recheckIndexes, NULL);
+ &hsearchslot->tuple->t_self, NULL, tuple,
+ recheckIndexes, NULL);
list_free(recheckIndexes);
}
@@ -519,9 +530,11 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
bool skip_tuple = false;
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
Relation rel = resultRelInfo->ri_RelationDesc;
+ HeapTupleTableSlot *hsearchslot = (HeapTupleTableSlot *)searchslot;
- /* For now we support only tables. */
+ /* For now we support only tables and heap tuples. */
Assert(rel->rd_rel->relkind == RELKIND_RELATION);
+ Assert(TTS_IS_HEAPTUPLE(searchslot) || TTS_IS_BUFFERTUPLE(searchslot));
CheckCmdReplicaIdentity(rel, CMD_DELETE);
@@ -530,8 +543,8 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
resultRelInfo->ri_TrigDesc->trig_delete_before_row)
{
skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
- &searchslot->tts_tuple->t_self,
- NULL, NULL);
+ &hsearchslot->tuple->t_self, NULL,
+ NULL);
}
if (!skip_tuple)
@@ -539,11 +552,11 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
List *recheckIndexes = NIL;
/* OK, delete the tuple */
- simple_heap_delete(rel, &searchslot->tts_tuple->t_self);
+ simple_heap_delete(rel, &hsearchslot->tuple->t_self);
/* AFTER ROW DELETE Triggers */
ExecARDeleteTriggers(estate, resultRelInfo,
- &searchslot->tts_tuple->t_self, NULL, NULL);
+ &hsearchslot->tuple->t_self, NULL, NULL);
list_free(recheckIndexes);
}
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index 233cc280608..d90bb16b570 100644
--- a/src/backend/executor/execScan.c
+++ b/src/backend/executor/execScan.c
@@ -78,8 +78,8 @@ ExecScanFetch(ScanState *node,
return ExecClearTuple(slot);
/* Store test tuple in the plan node's scan slot */
- ExecStoreHeapTuple(estate->es_epqTuple[scanrelid - 1],
- slot, false);
+ ExecForceStoreHeapTuple(estate->es_epqTuple[scanrelid - 1],
+ slot);
/* Check if it meets the access-method conditions */
if (!(*recheckMtd) (node, slot))
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index bb618e94f5d..bf49c4789cb 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -71,12 +71,1024 @@
static TupleDesc ExecTypeFromTLInternal(List *targetList,
bool hasoid, bool skipjunk);
+static void tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer);
const TupleTableSlotOps TTSOpsVirtual;
const TupleTableSlotOps TTSOpsHeapTuple;
const TupleTableSlotOps TTSOpsMinimalTuple;
const TupleTableSlotOps TTSOpsBufferTuple;
+/*
+ * slot_deform_heap_tuple
+ * Given a TupleTableSlot, extract data from the slot's physical tuple
+ * into its Datum/isnull arrays. Data is extracted up through the
+ * natts'th column (caller must ensure this is a legal column number).
+ *
+ * This is essentially an incremental version of heap_deform_tuple:
+ * on each call we extract attributes up to the one needed, without
+ * re-computing information about previously extracted attributes.
+ * slot->tts_nvalid is the number of attributes already extracted.
+ */
+static inline void __attribute__((always_inline))
+slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
+ int natts)
+{
+ TupleDesc tupleDesc = slot->tts_tupleDescriptor;
+ Datum *values = slot->tts_values;
+ bool *isnull = slot->tts_isnull;
+ HeapTupleHeader tup = tuple->t_data;
+ bool hasnulls = HeapTupleHasNulls(tuple);
+ int attnum;
+ char *tp; /* ptr to tuple data */
+ uint32 off; /* offset in tuple data */
+ bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
+ bool slow; /* can we use/set attcacheoff? */
+
+ /* We can only fetch as many attributes as the tuple has. */
+ natts = Min(HeapTupleHeaderGetNatts(tuple->t_data), natts);
+
+ /*
+ * Check whether the first call for this tuple, and initialize or restore
+ * loop state.
+ */
+ attnum = slot->tts_nvalid;
+ if (attnum == 0)
+ {
+ /* Start from the first attribute */
+ off = 0;
+ slow = false;
+ }
+ else
+ {
+ /* Restore state from previous execution */
+ off = *offp;
+ slow = TTS_SLOW(slot);
+ }
+
+ tp = (char *) tup + tup->t_hoff;
+
+ for (; attnum < natts; attnum++)
+ {
+ Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum);
+
+ if (hasnulls && att_isnull(attnum, bp))
+ {
+ values[attnum] = (Datum) 0;
+ isnull[attnum] = true;
+ slow = true; /* can't use attcacheoff anymore */
+ continue;
+ }
+
+ isnull[attnum] = false;
+
+ if (!slow && thisatt->attcacheoff >= 0)
+ off = thisatt->attcacheoff;
+ else if (thisatt->attlen == -1)
+ {
+ /*
+ * We can only cache the offset for a varlena attribute if the
+ * offset is already suitably aligned, so that there would be no
+ * pad bytes in any case: then the offset will be valid for either
+ * an aligned or unaligned value.
+ */
+ if (!slow &&
+ off == att_align_nominal(off, thisatt->attalign))
+ thisatt->attcacheoff = off;
+ else
+ {
+ off = att_align_pointer(off, thisatt->attalign, -1,
+ tp + off);
+ slow = true;
+ }
+ }
+ else
+ {
+ /* not varlena, so safe to use att_align_nominal */
+ off = att_align_nominal(off, thisatt->attalign);
+
+ if (!slow)
+ thisatt->attcacheoff = off;
+ }
+
+ values[attnum] = fetchatt(thisatt, tp + off);
+
+ off = att_addlength_pointer(off, thisatt->attlen, tp + off);
+
+ if (thisatt->attlen <= 0)
+ slow = true; /* can't use attcacheoff anymore */
+ }
+
+ /*
+ * Save state for next execution
+ */
+ slot->tts_nvalid = attnum;
+ *offp = off;
+ if (slow)
+ slot->tts_flags |= TTS_FLAG_SLOW;
+ else
+ slot->tts_flags &= ~TTS_FLAG_SLOW;
+}
+
+/*
+ * TupleTableSlotOps implementations.
+ */
+
+/*
+ * TupleTableSlotOps implementation for VirtualTupleTableSlot.
+ */
+static void
+tts_virtual_init(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_virtual_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_virtual_clear(TupleTableSlot *slot)
+{
+ if (unlikely(TTS_SHOULDFREE(slot)))
+ {
+ VirtualTupleTableSlot *vslot = (VirtualTupleTableSlot *) slot;
+
+ pfree(vslot->data);
+ vslot->data = NULL;
+
+ slot->tts_flags = ~TTS_FLAG_SHOULDFREE;
+ }
+
+ slot->tts_nvalid = 0;
+ slot->tts_flags |= TTS_FLAG_EMPTY;
+}
+
+/*
+ * Attribute values are readily available in tts_values and tts_isnull array
+ * in a VirtualTupleTableSlot. So there should be no need to call either of the
+ * following two functions.
+ */
+static void
+tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+ elog(ERROR, "getsomeattrs is not required to be called on a virtual tuple table slot");
+}
+
+static Datum
+tts_virtual_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+ elog(ERROR, "virtual tuple table slot does not have system atttributes");
+}
+
+/*
+ * To materialize a virtual slot all the datums that aren't passed by value
+ * have to be copied into the slot's memory context. To do so, count the
+ * required size, and allocate enough memory to store all attributes. That
+ * both gains efficiency, and makes it easier to release all the memory at
+ * once.
+ */
+static void
+tts_virtual_materialize(TupleTableSlot *slot)
+{
+ VirtualTupleTableSlot *vslot = (VirtualTupleTableSlot *) slot;
+ TupleDesc desc = slot->tts_tupleDescriptor;
+ Size sz = 0;
+ char *data;
+
+ /* already materialized */
+ if (TTS_SHOULDFREE(slot))
+ return;
+
+ /* compute size of memory required */
+ for (int natt = 0; natt < desc->natts; natt++)
+ {
+ Form_pg_attribute att = TupleDescAttr(desc, natt);
+ Datum val;
+
+ if (att->attbyval || slot->tts_isnull[natt])
+ continue;
+
+ val = slot->tts_values[natt];
+
+ if (att->attlen == -1 &&
+ VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val)))
+ {
+ /*
+ * We want to flatten the expanded value so that the materialized
+ * slot doesn't depend on it.
+ */
+ sz = att_align_nominal(sz, att->attalign);
+ sz += EOH_get_flat_size(DatumGetEOHP(val));
+ }
+ else
+ {
+ sz = att_align_nominal(sz, att->attalign);
+ sz = att_addlength_datum(sz, att->attlen, val);
+ }
+
+ /* FIXME: any reason to expand default args? */
+ }
+
+ /* all data is byval */
+ if (sz == 0)
+ return;
+
+ /* allocate memory */
+ vslot->data = data = MemoryContextAlloc(slot->tts_mcxt, sz);
+ slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+
+ /* and copy all attributes into the pre-allocated space */
+ for (int natt = 0; natt < desc->natts; natt++)
+ {
+ Form_pg_attribute att = TupleDescAttr(desc, natt);
+ Datum val;
+
+ if (att->attbyval || slot->tts_isnull[natt])
+ continue;
+
+ val = slot->tts_values[natt];
+
+ if (att->attlen == -1 &&
+ VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val)))
+ {
+ Size data_length;
+
+ /*
+ * We want to flatten the expanded value so that the materialized
+ * slot doesn't depend on it.
+ */
+ ExpandedObjectHeader *eoh = DatumGetEOHP(val);
+
+ data = (char *) att_align_nominal(data,
+ att->attalign);
+ data_length = EOH_get_flat_size(eoh);
+ EOH_flatten_into(eoh, data, data_length);
+
+ slot->tts_values[natt] = PointerGetDatum(data);
+ data += data_length;
+ }
+ else
+ {
+ Size data_length = 0;
+
+ data = (char *) att_align_nominal(data, att->attalign);
+ data_length = att_addlength_datum(data_length, att->attlen, val);
+
+ memcpy(data, DatumGetPointer(val), data_length);
+
+ slot->tts_values[natt] = PointerGetDatum(data);
+ data += data_length;
+ }
+ /* FIXME: any reason to expand default args? */
+ }
+}
+
+/*
+ * A virtual tuple table slot can not copy the datums into its own storage. So
+ * it can not copy contents of the other slot into its own memory context.
+ */
+static void
+tts_virtual_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+ TupleDesc srcdesc = dstslot->tts_tupleDescriptor;
+
+ Assert(srcdesc->natts <= dstslot->tts_tupleDescriptor->natts);
+
+ tts_virtual_clear(dstslot);
+
+ slot_getallattrs(srcslot);
+
+ for (int natt = 0; natt < srcdesc->natts; natt++)
+ {
+ dstslot->tts_values[natt] = srcslot->tts_values[natt];
+ dstslot->tts_isnull[natt] = srcslot->tts_isnull[natt];
+ }
+
+ dstslot->tts_nvalid = srcdesc->natts;
+ dstslot->tts_flags &= ~TTS_FLAG_EMPTY;
+
+ /* make sure storage doesn't depend on external memory */
+ tts_virtual_materialize(dstslot);
+}
+
+static HeapTuple
+tts_virtual_copy_heap_tuple(TupleTableSlot *slot)
+{
+ Assert(!TTS_EMPTY(slot));
+
+ return heap_form_tuple(slot->tts_tupleDescriptor,
+ slot->tts_values,
+ slot->tts_isnull);
+
+}
+
+static MinimalTuple
+tts_virtual_copy_minimal_tuple(TupleTableSlot *slot)
+{
+ Assert(!TTS_EMPTY(slot));
+
+ return heap_form_minimal_tuple(slot->tts_tupleDescriptor,
+ slot->tts_values,
+ slot->tts_isnull);
+}
+
+/*
+ * TupleTableSlotOps implementation for HeapTupleTableSlot.
+ */
+
+static void
+tts_heap_init(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_heap_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_heap_clear(TupleTableSlot *slot)
+{
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+ /* Free the memory for the heap tuple if it's allowed. */
+ if (TTS_SHOULDFREE(slot))
+ {
+ heap_freetuple(hslot->tuple);
+ slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
+ }
+
+ slot->tts_nvalid = 0;
+ slot->tts_flags |= TTS_FLAG_EMPTY;
+ hslot->off = 0;
+ hslot->tuple = NULL;
+}
+
+static void
+tts_heap_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+ Assert(!TTS_EMPTY(slot));
+
+ slot_deform_heap_tuple(slot, hslot->tuple, &hslot->off, natts);
+}
+
+static Datum
+tts_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+ return heap_getsysattr(hslot->tuple, attnum,
+ slot->tts_tupleDescriptor, isnull);
+}
+
+/*
+ * Materialize the heap tuple contained in the given slot into its own memory
+ * context.
+ */
+static void
+tts_heap_materialize(TupleTableSlot *slot)
+{
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+ MemoryContext oldContext;
+
+ Assert(!TTS_EMPTY(slot));
+
+ /* This slot has it's tuple already materialized. Nothing to do. */
+ if (TTS_SHOULDFREE(slot))
+ return;
+
+ slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+
+ oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+
+ if (!hslot->tuple)
+ hslot->tuple = heap_form_tuple(slot->tts_tupleDescriptor,
+ slot->tts_values,
+ slot->tts_isnull);
+ else
+ {
+ /*
+ * The tuple contained in this slot is not allocated in the memory
+ * context of the given slot (else it would have TTS_SHOULDFREE set).
+ * Copy the tuple into the given slot's memory context.
+ */
+ hslot->tuple = heap_copytuple(hslot->tuple);
+ }
+
+ slot->tts_nvalid = 0;
+ hslot->off = 0;
+
+ MemoryContextSwitchTo(oldContext);
+}
+
+/*
+ * Copy contents of the srcslot into dstslot, on which this callback has been
+ * invoked, in dstslot's memory context. We do this by creating a heap tuple
+ * from the source slot's contents in the memory context of the destination
+ * slot and then storing that heap tuple in the destination slot.
+ */
+static void
+tts_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+ HeapTuple tuple;
+ MemoryContext oldcontext;
+
+ oldcontext = MemoryContextSwitchTo(dstslot->tts_mcxt);
+ tuple = ExecCopySlotTuple(srcslot);
+ MemoryContextSwitchTo(oldcontext);
+
+ ExecStoreHeapTuple(tuple, dstslot, true);
+}
+
+/*
+ * Return the heap tuple in the slot as is if it contains one. Otherwise,
+ * materialize a heap tuple using contents of the slot and return it.
+ */
+static HeapTuple
+tts_heap_get_heap_tuple(TupleTableSlot *slot)
+{
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+ Assert(!TTS_EMPTY(slot));
+ if (!hslot->tuple)
+ tts_heap_materialize(slot);
+
+ return hslot->tuple;
+}
+
+/*
+ * Return a copy of heap tuple contained in the slot, materialising one if
+ * necessary.
+ */
+static HeapTuple
+tts_heap_copy_heap_tuple(TupleTableSlot *slot)
+{
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+ Assert(!TTS_EMPTY(slot));
+ if (!hslot->tuple)
+ tts_heap_materialize(slot);
+
+ return heap_copytuple(hslot->tuple);
+}
+
+/*
+ * Return a minimal tuple constructed from the contents of the slot.
+ *
+ * We always return a new minimal tuple so no copy, per say, is needed.
+ */
+static MinimalTuple
+tts_heap_copy_minimal_tuple(TupleTableSlot *slot)
+{
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+ if (!hslot->tuple)
+ tts_heap_materialize(slot);
+
+ return minimal_tuple_from_heap_tuple(hslot->tuple);
+}
+
+/*
+ * Store the given tuple into the given HeapTupleTableSlot. If the slot
+ * already contains a tuple, we will free the memory for the same before
+ * storing a new one there.
+ */
+static void
+tts_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, bool shouldFree)
+{
+ HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+ tts_heap_clear(slot);
+
+ slot->tts_nvalid = 0;
+ hslot->tuple = tuple;
+ hslot->off = 0;
+ slot->tts_flags &= ~TTS_FLAG_EMPTY;
+
+ if (shouldFree)
+ slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+}
+
+
+static void
+tts_minimal_init(TupleTableSlot *slot)
+{
+ MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+ /*
+ * Initialize the heap tuple pointer to access attributes of the minimal
+ * tuple contained in the slot as if its a heap tuple.
+ */
+ mslot->tuple = &mslot->minhdr;
+}
+
+static void
+tts_minimal_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_minimal_clear(TupleTableSlot *slot)
+{
+ MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+ if (TTS_SHOULDFREE(slot))
+ {
+ heap_free_minimal_tuple(mslot->mintuple);
+ slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
+ }
+
+ slot->tts_nvalid = 0;
+ slot->tts_flags |= TTS_FLAG_EMPTY;
+ mslot->off = 0;
+ mslot->mintuple = NULL;
+}
+
+static void
+tts_minimal_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+ MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+ Assert(!TTS_EMPTY(slot));
+
+ slot_deform_heap_tuple(slot, mslot->tuple, &mslot->off, natts);
+}
+
+static Datum
+tts_minimal_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+ elog(ERROR, "minimal tuple table slot does not have system atttributes");
+}
+
+/*
+ * Materialize the minimal tuple contained in the given slot into its own
+ * memory context.
+ */
+static void
+tts_minimal_materialize(TupleTableSlot *slot)
+{
+ MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+ MemoryContext oldContext;
+
+ Assert(!TTS_EMPTY(slot));
+
+ /* This slot has it's tuple already materialized. Nothing to do. */
+ if (TTS_SHOULDFREE(slot))
+ return;
+
+ slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+ oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+
+ if (!mslot->mintuple)
+ mslot->mintuple = heap_form_minimal_tuple(slot->tts_tupleDescriptor,
+ slot->tts_values,
+ slot->tts_isnull);
+ else
+ {
+ /*
+ * The minimal tuple contained in this slot is not allocated in the
+ * memory context of the given slot (else it would have TTS_SHOULDFREE
+ * set). Copy the minimal tuple into the given slot's memory context.
+ */
+ mslot->mintuple = heap_copy_minimal_tuple(mslot->mintuple);
+ }
+
+ Assert(mslot->tuple == &mslot->minhdr);
+
+ mslot->minhdr.t_len = mslot->mintuple->t_len + MINIMAL_TUPLE_OFFSET;
+ mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mslot->mintuple - MINIMAL_TUPLE_OFFSET);
+
+ MemoryContextSwitchTo(oldContext);
+
+ slot->tts_nvalid = 0;
+ mslot->off = 0;
+}
+
+/*
+ * Copy contents of the srcslot into dstslot, on which this callback has been
+ * invoked, in dstslot's memory context. We do this by creating a minimal tuple
+ * from the source slot's contents in the memory context of the destination
+ * slot and then storing that minimal tuple in the destination slot.
+ */
+static void
+tts_minimal_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+ MemoryContext oldcontext;
+ MinimalTuple mintuple;
+
+ oldcontext = MemoryContextSwitchTo(dstslot->tts_mcxt);
+ mintuple = ExecCopySlotMinimalTuple(srcslot);
+ MemoryContextSwitchTo(oldcontext);
+
+ ExecStoreMinimalTuple(mintuple, dstslot, true);
+}
+
+/*
+ * Return the minimal tuple if slot contains one. Otherwise materialize the
+ * contents of slot into a minimal tuple and return that.
+ */
+static MinimalTuple
+tts_minimal_get_minimal_tuple(TupleTableSlot *slot)
+{
+ MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+ Assert(!TTS_EMPTY(slot));
+
+ if (!mslot->mintuple)
+ tts_minimal_materialize(slot);
+
+ return mslot->mintuple;
+}
+
+/*
+ * Return a heap tuple constructed from the minimal tuple contained in the slot.
+ *
+ * We always construct a new heap tuple, so there is nothing to copy as such.
+ */
+static HeapTuple
+tts_minimal_copy_heap_tuple(TupleTableSlot *slot)
+{
+ MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+ /* Materialize the minimal tuple if not already present. */
+ if (!mslot->mintuple)
+ tts_minimal_materialize(slot);
+
+ return heap_tuple_from_minimal_tuple(mslot->mintuple);
+}
+
+/*
+ * Return a copy of minimal tuple contained in the slot, materializing one if
+ * necessary.
+ */
+static MinimalTuple
+tts_minimal_copy_minimal_tuple(TupleTableSlot *slot)
+{
+ MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+ if (!mslot->mintuple)
+ tts_minimal_materialize(slot);
+
+ return heap_copy_minimal_tuple(mslot->mintuple);
+}
+
+/*
+ * Store the given minimal tuple into the given MinimalTupleTableSlot. If the
+ * slot already contains a tuple, we will free the memory for the same before
+ * storing a new one there.
+ */
+static void
+tts_minimal_store_tuple(TupleTableSlot *slot, MinimalTuple mtup, bool shouldFree)
+{
+ MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+ tts_minimal_clear(slot);
+
+ Assert(!TTS_SHOULDFREE(slot));
+ Assert(TTS_EMPTY(slot));
+
+ slot->tts_flags &= ~TTS_FLAG_EMPTY;
+ slot->tts_nvalid = 0;
+ mslot->off = 0;
+
+ mslot->mintuple = mtup;
+ Assert(mslot->tuple == &mslot->minhdr);
+ mslot->minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
+ mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
+ /* no need to set t_self or t_tableOid since we won't allow access */
+
+ if (shouldFree)
+ slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+ else
+ Assert(!TTS_SHOULDFREE(slot));
+}
+
+/*
+ * TupleTableSlotOps implementation for BufferHeapTupleTableSlot.
+ */
+
+static void
+tts_buffer_heap_init(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_buffer_heap_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_buffer_heap_clear(TupleTableSlot *slot)
+{
+ BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+ /*
+ * Free the memory for heap tuple if allowed. A tuple coming from buffer
+ * can never be freed. But we may have materialized a tuple from buffer.
+ * Such a tuple can be freed.
+ */
+ if (TTS_SHOULDFREE(slot))
+ {
+ /* We should have unpinned the buffer while materializing the tuple. */
+ Assert(!BufferIsValid(bslot->buffer));
+
+ heap_freetuple(bslot->base.tuple);
+ slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
+
+ Assert(!BufferIsValid(bslot->buffer));
+ }
+
+ if (BufferIsValid(bslot->buffer))
+ ReleaseBuffer(bslot->buffer);
+
+ slot->tts_nvalid = 0;
+ slot->tts_flags |= TTS_FLAG_EMPTY;
+ bslot->base.tuple = NULL;
+ bslot->base.off = 0;
+ bslot->buffer = InvalidBuffer;
+}
+
+static void
+tts_buffer_heap_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+ BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+ Assert(!TTS_EMPTY(slot));
+
+ slot_deform_heap_tuple(slot, bslot->base.tuple, &bslot->base.off, natts);
+}
+
+static Datum
+tts_buffer_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+ BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+ return heap_getsysattr(bslot->base.tuple, attnum,
+ slot->tts_tupleDescriptor, isnull);
+}
+
+/*
+ * Materialize the heap tuple contained in the given slot into its own memory
+ * context.
+ */
+static void
+tts_buffer_heap_materialize(TupleTableSlot *slot)
+{
+ BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+ MemoryContext oldContext;
+
+ Assert(!TTS_EMPTY(slot));
+
+ /* If already materialized nothing to do. */
+ if (TTS_SHOULDFREE(slot))
+ return;
+
+ slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+ oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+
+ if (!bslot->base.tuple)
+ {
+ /*
+ * A heap tuple stored in a BufferHeapTupleTableSlot should have a
+ * buffer associated with it, unless it's materialized. Thus it will
+ * never happen that there is no heap tuple stored in this slot but
+ * tts_values and tts_isnull is set. IOW, we should never require to construct a
+ * tuple from tts_values and tts_isnull in this slot.
+ */
+ elog(ERROR, "a buffer tuple table slot should never require to construct a tuple from datums");
+ }
+ bslot->base.tuple = heap_copytuple(bslot->base.tuple);
+ MemoryContextSwitchTo(oldContext);
+
+ /*
+ * A heap tuple stored in a BufferHeapTupleTableSlot should have a buffer
+ * associated with it, unless it's materialized.
+ */
+ Assert(BufferIsValid(bslot->buffer));
+ ReleaseBuffer(bslot->buffer);
+ bslot->buffer = InvalidBuffer;
+
+ bslot->base.off = 0;
+ slot->tts_nvalid = 0;
+}
+
+/*
+ * A buffer tuple table slot is used to store an on-disk tuple in it, at least
+ * to start with. So a need to copy into a buffer tuple table slot should not
+ * arise. May be we could support copying from a buffer tuple table slot, but
+ * it is not clear why it's required to do that.
+ */
+static void
+tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+ BufferHeapTupleTableSlot *bsrcslot = (BufferHeapTupleTableSlot *) srcslot;
+ BufferHeapTupleTableSlot *bdstslot = (BufferHeapTupleTableSlot *) dstslot;
+
+ Assert(dstslot->tts_cb == srcslot->tts_cb);
+
+ if (TTS_SHOULDFREE(srcslot))
+ {
+ MemoryContext oldContext;
+
+ ExecClearTuple(dstslot);
+ dstslot->tts_flags |= TTS_FLAG_SHOULDFREE;
+ dstslot->tts_flags &= ~TTS_FLAG_EMPTY;
+ oldContext = MemoryContextSwitchTo(dstslot->tts_mcxt);
+ bdstslot->base.tuple = heap_copytuple(bsrcslot->base.tuple);
+ MemoryContextSwitchTo(oldContext);
+ }
+ else
+ {
+ tts_buffer_heap_store_tuple(dstslot, bsrcslot->base.tuple, bsrcslot->buffer);
+ tts_buffer_heap_materialize(dstslot);
+ }
+}
+
+/*
+ * Return the heap tuple in the slot as is if it contains one. Otherwise,
+ * materialize a heap tuple using contents of the slot and return it.
+ */
+static HeapTuple
+tts_buffer_heap_get_heap_tuple(TupleTableSlot *slot)
+{
+ BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+ Assert(!TTS_EMPTY(slot));
+
+ /* Is this even possible for a buffer tuple? */
+ if (!bslot->base.tuple)
+ tts_buffer_heap_materialize(slot);
+
+ return bslot->base.tuple;
+}
+
+/*
+ * Return a copy of heap tuple contained in the slot, materialising one if
+ * necessary.
+ */
+static HeapTuple
+tts_buffer_heap_copy_heap_tuple(TupleTableSlot *slot)
+{
+ BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+ Assert(!TTS_EMPTY(slot));
+
+ /* Is this even possible for a buffer tuple? */
+ if (!bslot->base.tuple)
+ tts_buffer_heap_materialize(slot);
+
+ return heap_copytuple(bslot->base.tuple);
+}
+
+/*
+ * Return a minimal tuple constructed from the contents of the slot.
+ *
+ * We always return a new minimal tuple so no copy, per say, is needed.
+ */
+static MinimalTuple
+tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot)
+{
+ BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+ Assert(!TTS_EMPTY(slot));
+
+ /* Is this even possible for a buffer tuple? */
+ if (!bslot->base.tuple)
+ tts_buffer_heap_materialize(slot);
+
+ return minimal_tuple_from_heap_tuple(bslot->base.tuple);
+}
+
+/*
+ * Store the given tuple into the given BufferHeapTupleTableSlot and pin the
+ * given buffer. If the tuple already contained in the slot can be freed free
+ * it.
+ */
+static void
+tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer)
+{
+ BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+ if (TTS_SHOULDFREE(slot))
+ {
+ /*
+ * A heap tuple stored in a BufferHeapTupleTableSlot should have a
+ * buffer associated with it, unless it's materialized.
+ */
+ Assert(!BufferIsValid(bslot->buffer));
+
+ heap_freetuple(bslot->base.tuple);
+ slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
+ }
+
+ slot->tts_flags &= ~TTS_FLAG_EMPTY;
+ slot->tts_nvalid = 0;
+ bslot->base.tuple = tuple;
+ bslot->base.off = 0;
+
+ /*
+ * If tuple is on a disk page, keep the page pinned as long as we hold a
+ * pointer into it. We assume the caller already has such a pin.
+ *
+ * This is coded to optimize the case where the slot previously held a
+ * tuple on the same disk page: in that case releasing and re-acquiring
+ * the pin is a waste of cycles. This is a common situation during
+ * seqscans, so it's worth troubling over.
+ */
+ if (bslot->buffer != buffer)
+ {
+ if (BufferIsValid(bslot->buffer))
+ ReleaseBuffer(bslot->buffer);
+ bslot->buffer = buffer;
+ IncrBufferRefCount(buffer);
+ }
+}
+
+/*
+ * TupleTableSlotOps for each of TupleTableSlotTypes. These are used to
+ * identify the type of slot.
+ */
+const TupleTableSlotOps TTSOpsVirtual = {
+ .base_slot_size = sizeof(VirtualTupleTableSlot),
+ .init = tts_virtual_init,
+ .release = tts_virtual_release,
+ .clear = tts_virtual_clear,
+ .getsomeattrs = tts_virtual_getsomeattrs,
+ .getsysattr = tts_virtual_getsysattr,
+ .materialize = tts_virtual_materialize,
+ .copyslot = tts_virtual_copyslot,
+
+ /*
+ * A virtual tuple table slot can not "own" a heap tuple or a minimal
+ * tuple.
+ */
+ .get_heap_tuple = NULL,
+ .get_minimal_tuple = NULL,
+ .copy_heap_tuple = tts_virtual_copy_heap_tuple,
+ .copy_minimal_tuple = tts_virtual_copy_minimal_tuple
+};
+
+const TupleTableSlotOps TTSOpsHeapTuple = {
+ .base_slot_size = sizeof(HeapTupleTableSlot),
+ .init = tts_heap_init,
+ .release = tts_heap_release,
+ .clear = tts_heap_clear,
+ .getsomeattrs = tts_heap_getsomeattrs,
+ .getsysattr = tts_heap_getsysattr,
+ .materialize = tts_heap_materialize,
+ .copyslot = tts_heap_copyslot,
+ .get_heap_tuple = tts_heap_get_heap_tuple,
+
+ /* A heap tuple table slot can not "own" a minimal tuple. */
+ .get_minimal_tuple = NULL,
+ .copy_heap_tuple = tts_heap_copy_heap_tuple,
+ .copy_minimal_tuple = tts_heap_copy_minimal_tuple
+};
+
+const TupleTableSlotOps TTSOpsMinimalTuple = {
+ .base_slot_size = sizeof(MinimalTupleTableSlot),
+ .init = tts_minimal_init,
+ .release = tts_minimal_release,
+ .clear = tts_minimal_clear,
+ .getsomeattrs = tts_minimal_getsomeattrs,
+ .getsysattr = tts_minimal_getsysattr,
+ .materialize = tts_minimal_materialize,
+ .copyslot = tts_minimal_copyslot,
+
+ /*
+ * A minimal tuple table slot can not "own" a heap tuple. As mentioned in
+ * the prologue of MinimalTupleData, a minimal tuple may be presented as a
+ * heap tuple, but such a representation does not have memory to hold
+ * system attributes in it and should be used for accessing/manipulating
+ * tuple through a slot. Hence we do not return heap tuple representation
+ * crafted from a minimal tuple to be returned in get_heap_tuple callback
+ * of this TupleTableSlotType.
+ */
+ .get_heap_tuple = NULL,
+ .get_minimal_tuple = tts_minimal_get_minimal_tuple,
+ .copy_heap_tuple = tts_minimal_copy_heap_tuple,
+ .copy_minimal_tuple = tts_minimal_copy_minimal_tuple
+};
+
+const TupleTableSlotOps TTSOpsBufferTuple = {
+ .base_slot_size = sizeof(BufferHeapTupleTableSlot),
+ .init = tts_buffer_heap_init,
+ .release = tts_buffer_heap_release,
+ .clear = tts_buffer_heap_clear,
+ .getsomeattrs = tts_buffer_heap_getsomeattrs,
+ .getsysattr = tts_buffer_heap_getsysattr,
+ .materialize = tts_buffer_heap_materialize,
+ .copyslot = tts_buffer_heap_copyslot,
+ .get_heap_tuple = tts_buffer_heap_get_heap_tuple,
+
+ /* A buffer heap tuple table slot can not "own" a minimal tuple. */
+ .get_minimal_tuple = NULL,
+ .copy_heap_tuple = tts_buffer_heap_copy_heap_tuple,
+ .copy_minimal_tuple = tts_buffer_heap_copy_minimal_tuple
+};
+
/* ----------------------------------------------------------------
* tuple table create/delete functions
* ----------------------------------------------------------------
@@ -85,58 +1097,60 @@ const TupleTableSlotOps TTSOpsBufferTuple;
/* --------------------------------
* MakeTupleTableSlot
*
- * Basic routine to make an empty TupleTableSlot. If tupleDesc is
- * specified the slot's descriptor is fixed for it's lifetime, gaining
- * some efficiency. If that's undesirable, pass NULL.
+ * Basic routine to make an empty TupleTableSlot of given
+ * TupleTableSlotType. If tupleDesc is specified the slot's descriptor is
+ * fixed for it's lifetime, gaining some efficiency. If that's
+ * undesirable, pass NULL.
* --------------------------------
*/
TupleTableSlot *
MakeTupleTableSlot(TupleDesc tupleDesc,
const TupleTableSlotOps *tts_cb)
{
- Size sz;
+ Size basesz, allocsz;
TupleTableSlot *slot;
+ basesz = tts_cb->base_slot_size;
/*
* When a fixed descriptor is specified, we can reduce overhead by
* allocating the entire slot in one go.
*/
if (tupleDesc)
- sz = MAXALIGN(sizeof(TupleTableSlot)) +
+ allocsz = MAXALIGN(basesz) +
MAXALIGN(tupleDesc->natts * sizeof(Datum)) +
MAXALIGN(tupleDesc->natts * sizeof(bool));
else
- sz = sizeof(TupleTableSlot);
+ allocsz = basesz;
- slot = palloc0(sz);
+ slot = palloc0(allocsz);
/* const for optimization purposes, OK to modify at allocation time */
*((const TupleTableSlotOps **) &slot->tts_cb) = tts_cb;
slot->type = T_TupleTableSlot;
slot->tts_flags |= TTS_FLAG_EMPTY;
if (tupleDesc != NULL)
slot->tts_flags |= TTS_FLAG_FIXED;
- slot->tts_tuple = NULL;
slot->tts_tupleDescriptor = tupleDesc;
slot->tts_mcxt = CurrentMemoryContext;
- slot->tts_buffer = InvalidBuffer;
slot->tts_nvalid = 0;
- slot->tts_values = NULL;
- slot->tts_isnull = NULL;
- slot->tts_mintuple = NULL;
if (tupleDesc != NULL)
{
slot->tts_values = (Datum *)
(((char *) slot)
- + MAXALIGN(sizeof(TupleTableSlot)));
+ + MAXALIGN(basesz));
slot->tts_isnull = (bool *)
(((char *) slot)
- + MAXALIGN(sizeof(TupleTableSlot))
+ + MAXALIGN(basesz)
+ MAXALIGN(tupleDesc->natts * sizeof(Datum)));
PinTupleDesc(tupleDesc);
}
+ /*
+ * And allow slot type specific initialization.
+ */
+ slot->tts_cb->init(slot);
+
return slot;
}
@@ -178,6 +1192,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
/* Always release resources and reset the slot to empty */
ExecClearTuple(slot);
+ slot->tts_cb->release(slot);
if (slot->tts_tupleDescriptor)
{
ReleaseTupleDesc(slot->tts_tupleDescriptor);
@@ -234,6 +1249,7 @@ ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
/* This should match ExecResetTupleTable's processing of one slot */
Assert(IsA(slot, TupleTableSlot));
ExecClearTuple(slot);
+ slot->tts_cb->release(slot);
if (slot->tts_tupleDescriptor)
ReleaseTupleDesc(slot->tts_tupleDescriptor);
if (!TTS_FIXED(slot))
@@ -334,36 +1350,9 @@ ExecStoreHeapTuple(HeapTuple tuple,
Assert(slot != NULL);
Assert(slot->tts_tupleDescriptor != NULL);
- /*
- * Free any old physical tuple belonging to the slot.
- */
- if (TTS_SHOULDFREE(slot))
- {
- heap_freetuple(slot->tts_tuple);
- slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
- }
- if (TTS_SHOULDFREEMIN(slot))
- {
- heap_free_minimal_tuple(slot->tts_mintuple);
- slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
- }
-
- /*
- * Store the new tuple into the specified slot.
- */
- slot->tts_flags &= ~TTS_FLAG_EMPTY;
- if (shouldFree)
- slot->tts_flags |= TTS_FLAG_SHOULDFREE;
- slot->tts_tuple = tuple;
- slot->tts_mintuple = NULL;
-
- /* Mark extracted state invalid */
- slot->tts_nvalid = 0;
-
- /* Unpin any buffer pinned by the slot. */
- if (BufferIsValid(slot->tts_buffer))
- ReleaseBuffer(slot->tts_buffer);
- slot->tts_buffer = InvalidBuffer;
+ if (!TTS_IS_HEAPTUPLE(slot))
+ elog(ERROR, "trying to store a heap tuple into wrong type of slot");
+ tts_heap_store_tuple(slot, tuple, shouldFree);
return slot;
}
@@ -397,46 +1386,9 @@ ExecStoreBufferHeapTuple(HeapTuple tuple,
Assert(slot->tts_tupleDescriptor != NULL);
Assert(BufferIsValid(buffer));
- /*
- * Free any old physical tuple belonging to the slot.
- */
- if (TTS_SHOULDFREE(slot))
- {
- heap_freetuple(slot->tts_tuple);
- slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
- }
- if (TTS_SHOULDFREEMIN(slot))
- {
- heap_free_minimal_tuple(slot->tts_mintuple);
- slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
- }
-
- /*
- * Store the new tuple into the specified slot.
- */
- slot->tts_flags &= ~TTS_FLAG_EMPTY;
- slot->tts_tuple = tuple;
- slot->tts_mintuple = NULL;
-
- /* Mark extracted state invalid */
- slot->tts_nvalid = 0;
-
- /*
- * Keep the disk page containing the given tuple pinned as long as we hold
- * a pointer into it. We assume the caller already has such a pin.
- *
- * This is coded to optimize the case where the slot previously held a
- * tuple on the same disk page: in that case releasing and re-acquiring the
- * pin is a waste of cycles. This is a common situation during seqscans,
- * so it's worth troubling over.
- */
- if (slot->tts_buffer != buffer)
- {
- if (BufferIsValid(slot->tts_buffer))
- ReleaseBuffer(slot->tts_buffer);
- slot->tts_buffer = buffer;
- IncrBufferRefCount(buffer);
- }
+ if (!TTS_IS_BUFFERTUPLE(slot))
+ elog(ERROR, "trying to store an on-disk heap tuple into wrong type of slot");
+ tts_buffer_heap_store_tuple(slot, tuple, buffer);
return slot;
}
@@ -461,93 +1413,9 @@ ExecStoreMinimalTuple(MinimalTuple mtup,
Assert(slot != NULL);
Assert(slot->tts_tupleDescriptor != NULL);
- /*
- * Free any old physical tuple belonging to the slot.
- */
- if (TTS_SHOULDFREE(slot))
- {
- heap_freetuple(slot->tts_tuple);
- slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
- }
- if (TTS_SHOULDFREEMIN(slot))
- {
- heap_free_minimal_tuple(slot->tts_mintuple);
- slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
- }
-
- /*
- * Drop the pin on the referenced buffer, if there is one.
- */
- if (BufferIsValid(slot->tts_buffer))
- ReleaseBuffer(slot->tts_buffer);
-
- slot->tts_buffer = InvalidBuffer;
-
- /*
- * Store the new tuple into the specified slot.
- */
- slot->tts_flags &= ~TTS_FLAG_EMPTY;
- if (shouldFree)
- slot->tts_flags |= TTS_FLAG_SHOULDFREEMIN;
- slot->tts_tuple = &slot->tts_minhdr;
- slot->tts_mintuple = mtup;
-
- slot->tts_minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
- slot->tts_minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
- /* no need to set t_self or t_tableOid since we won't allow access */
-
- /* Mark extracted state invalid */
- slot->tts_nvalid = 0;
-
- return slot;
-}
-
-/* --------------------------------
- * ExecClearTuple
- *
- * This function is used to clear out a slot in the tuple table.
- *
- * NB: only the tuple is cleared, not the tuple descriptor (if any).
- * --------------------------------
- */
-TupleTableSlot * /* return: slot passed */
-ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */
-{
- /*
- * sanity checks
- */
- Assert(slot != NULL);
-
- /*
- * Free the old physical tuple if necessary.
- */
- if (TTS_SHOULDFREE(slot))
- {
- heap_freetuple(slot->tts_tuple);
- slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
- }
- if (TTS_SHOULDFREEMIN(slot))
- {
- heap_free_minimal_tuple(slot->tts_mintuple);
- slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
- }
-
- slot->tts_tuple = NULL;
- slot->tts_mintuple = NULL;
-
- /*
- * Drop the pin on the referenced buffer, if there is one.
- */
- if (BufferIsValid(slot->tts_buffer))
- ReleaseBuffer(slot->tts_buffer);
-
- slot->tts_buffer = InvalidBuffer;
-
- /*
- * Mark it empty.
- */
- slot->tts_flags |= TTS_FLAG_EMPTY;
- slot->tts_nvalid = 0;
+ if (!TTS_IS_MINIMALTUPLE(slot))
+ elog(ERROR, "trying to store a minimal tuple into wrong type of slot");
+ tts_minimal_store_tuple(slot, mtup, shouldFree);
return slot;
}
@@ -611,79 +1479,19 @@ ExecStoreAllNullTuple(TupleTableSlot *slot)
}
/* --------------------------------
- * ExecCopySlotTuple
- * Obtain a copy of a slot's regular physical tuple. The copy is
- * palloc'd in the current memory context.
- * The slot itself is undisturbed.
+ * ExecFetchSlotTuple
+ * Fetch the slot's regular physical tuple.
*
- * This works even if the slot contains a virtual or minimal tuple;
- * however the "system columns" of the result will not be meaningful.
+ * This is a thin wrapper around TupleTableSlotType specific
+ * get_heap_tuple callback. The callback is expected to return a heap
+ * tuple as is if it holds one and continue to have ownership of the heap
+ * tuple. If materialize is true, the function calls TupleTableSlotType
+ * specific materialize() callback which is expected to materialize the
+ * tuple within the slot so that the slot "owns" it. If materialize is
+ * false, the returned tuple is not guaranteed to have storage local to
+ * the slot and hence should be treated as read-only.
* --------------------------------
*/
-HeapTuple
-ExecCopySlotTuple(TupleTableSlot *slot)
-{
- /*
- * sanity checks
- */
- Assert(slot != NULL);
- Assert(!TTS_EMPTY(slot));
-
- /*
- * If we have a physical tuple (either format) then just copy it.
- */
- if (TTS_HAS_PHYSICAL_TUPLE(slot))
- return heap_copytuple(slot->tts_tuple);
- if (slot->tts_mintuple)
- return heap_tuple_from_minimal_tuple(slot->tts_mintuple);
-
- /*
- * Otherwise we need to build a tuple from the Datum array.
- */
- return heap_form_tuple(slot->tts_tupleDescriptor,
- slot->tts_values,
- slot->tts_isnull);
-}
-
-/* --------------------------------
- * ExecCopySlotMinimalTuple
- * Obtain a copy of a slot's minimal physical tuple. The copy is
- * palloc'd in the current memory context.
- * The slot itself is undisturbed.
- * --------------------------------
- */
-MinimalTuple
-ExecCopySlotMinimalTuple(TupleTableSlot *slot)
-{
- /*
- * sanity checks
- */
- Assert(slot != NULL);
- Assert(!TTS_EMPTY(slot));
-
- /*
- * If we have a physical tuple then just copy it. Prefer to copy
- * tts_mintuple since that's a tad cheaper.
- */
- if (slot->tts_mintuple)
- return heap_copy_minimal_tuple(slot->tts_mintuple);
- if (slot->tts_tuple)
- {
- if (HeapTupleHeaderGetNatts(slot->tts_tuple->t_data)
- < slot->tts_tupleDescriptor->natts)
- return minimal_expand_tuple(slot->tts_tuple,
- slot->tts_tupleDescriptor);
- else
- return minimal_tuple_from_heap_tuple(slot->tts_tuple);
- }
-
- /*
- * Otherwise we need to build a tuple from the Datum array.
- */
- return heap_form_minimal_tuple(slot->tts_tupleDescriptor,
- slot->tts_values,
- slot->tts_isnull);
-}
/*
* ExecFetchSlotHeapTuple - fetch HeapTuple representing the slot's content
@@ -713,89 +1521,67 @@ ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
Assert(slot != NULL);
Assert(!TTS_EMPTY(slot));
- if (shouldFree)
- *shouldFree = false;
+ /* Materialize the tuple so that the slot "owns" it, if requested. */
+ if (materialize)
+ slot->tts_cb->materialize(slot);
- /*
- * If we have a regular physical tuple then just return it.
- */
- if (TTS_HAS_PHYSICAL_TUPLE(slot))
+ if (slot->tts_cb->get_heap_tuple == NULL)
{
- if (HeapTupleHeaderGetNatts(slot->tts_tuple->t_data) <
- slot->tts_tupleDescriptor->natts)
- {
- HeapTuple tuple;
- MemoryContext oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
-
- tuple = heap_expand_tuple(slot->tts_tuple,
- slot->tts_tupleDescriptor);
- MemoryContextSwitchTo(oldContext);
- slot = ExecStoreHeapTuple(tuple, slot, true);
- }
- return slot->tts_tuple;
+ if (shouldFree)
+ *shouldFree = true;
+ return slot->tts_cb->copy_heap_tuple(slot);
+ }
+ else
+ {
+ if (shouldFree)
+ *shouldFree = false;
+ return slot->tts_cb->get_heap_tuple(slot);
}
-
- /*
- * Otherwise materialize the slot...
- */
- ExecMaterializeSlot(slot);
-
- return slot->tts_tuple;
}
/* --------------------------------
* ExecFetchSlotMinimalTuple
* Fetch the slot's minimal physical tuple.
*
- * If the slot contains a virtual tuple, we convert it to minimal
- * physical form. The slot retains ownership of the minimal tuple.
- * If it contains a regular tuple we convert to minimal form and store
- * that in addition to the regular tuple (not instead of, because
- * callers may hold pointers to Datums within the regular tuple).
+ * If the given tuple table slot can hold a minimal tuple, indicated by a
+ * non-NULL get_minimal_tuple callback, the function returns the minimal
+ * tuple returned by that callback. It assumes that the minimal tuple
+ * returned by the callback is "owned" by the slot i.e. the slot is
+ * responsible for freeing the memory consumed by the tuple. Hence it sets
+ * *shouldFree to false, indicating that the caller should not free the
+ * memory consumed by the minimal tuple. In this case the returned minimal
+ * tuple should be considered as read-only.
*
- * As above, the result must be treated as read-only.
+ * If that callback is not supported, it calls copy_minimal_tuple callback
+ * which is expected to return a copy of minimal tuple represnting the
+ * contents of the slot. In this case *shouldFree is set to true,
+ * indicating the caller that it should free the memory consumed by the
+ * minimal tuple. In this case the returned minimal tuple may be written
+ * up.
* --------------------------------
*/
MinimalTuple
-ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
+ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
+ bool *shouldFree)
{
- MemoryContext oldContext;
-
/*
* sanity checks
*/
Assert(slot != NULL);
Assert(!TTS_EMPTY(slot));
- if (shouldFree)
- *shouldFree = false;
-
- /*
- * If we have a minimal physical tuple (local or not) then just return it.
- */
- if (slot->tts_mintuple)
- return slot->tts_mintuple;
-
- /*
- * Otherwise, copy or build a minimal tuple, and store it into the slot.
- *
- * We may be called in a context that is shorter-lived than the tuple
- * slot, but we have to ensure that the materialized tuple will survive
- * anyway.
- */
- oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
- slot->tts_mintuple = ExecCopySlotMinimalTuple(slot);
- slot->tts_flags |= TTS_FLAG_SHOULDFREEMIN;
- MemoryContextSwitchTo(oldContext);
-
- /*
- * Note: we may now have a situation where we have a local minimal tuple
- * attached to a virtual or non-local physical tuple. There seems no harm
- * in that at the moment, but if any materializes, we should change this
- * function to force the slot into minimal-tuple-only state.
- */
-
- return slot->tts_mintuple;
+ if (slot->tts_cb->get_minimal_tuple)
+ {
+ if (shouldFree)
+ *shouldFree = false;
+ return slot->tts_cb->get_minimal_tuple(slot);
+ }
+ else
+ {
+ if (shouldFree)
+ *shouldFree = true;
+ return slot->tts_cb->copy_minimal_tuple(slot);
+ }
}
/* --------------------------------
@@ -826,103 +1612,58 @@ ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)
return ret;
}
-/* ExecMaterializeSlot - force a slot into the "materialized" state.
- *
- * This causes the slot's tuple to be a local copy not dependent on any
- * external storage (i.e. pointing into a Buffer, or having allocations in
- * another memory context).
- *
- * A typical use for this operation is to prepare a computed tuple for being
- * stored on disk. The original data may or may not be virtual, but in any
- * case we need a private copy for heap_insert to scribble on.
- */
void
-ExecMaterializeSlot(TupleTableSlot *slot)
+ExecForceStoreHeapTuple(HeapTuple tuple,
+ TupleTableSlot *slot)
{
- MemoryContext oldContext;
+ if (TTS_IS_HEAPTUPLE(slot))
+ {
+ ExecStoreHeapTuple(tuple, slot, false);
+ }
+ else if (TTS_IS_BUFFERTUPLE(slot))
+ {
+ MemoryContext oldContext;
+ BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
- /*
- * sanity checks
- */
- Assert(slot != NULL);
- Assert(!TTS_EMPTY(slot));
-
- /*
- * If we have a regular physical tuple, and it's locally palloc'd, we have
- * nothing to do.
- */
- if (slot->tts_tuple && TTS_SHOULDFREE(slot))
- return;
-
- /*
- * Otherwise, copy or build a physical tuple, and store it into the slot.
- *
- * We may be called in a context that is shorter-lived than the tuple
- * slot, but we have to ensure that the materialized tuple will survive
- * anyway.
- */
- oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
- slot->tts_tuple = ExecCopySlotTuple(slot);
- slot->tts_flags |= TTS_FLAG_SHOULDFREE;
- MemoryContextSwitchTo(oldContext);
-
- /*
- * Drop the pin on the referenced buffer, if there is one.
- */
- if (BufferIsValid(slot->tts_buffer))
- ReleaseBuffer(slot->tts_buffer);
-
- slot->tts_buffer = InvalidBuffer;
-
- /*
- * Mark extracted state invalid. This is important because the slot is
- * not supposed to depend any more on the previous external data; we
- * mustn't leave any dangling pass-by-reference datums in tts_values.
- * However, we have not actually invalidated any such datums, if there
- * happen to be any previously fetched from the slot. (Note in particular
- * that we have not pfree'd tts_mintuple, if there is one.)
- */
- slot->tts_nvalid = 0;
-
- /*
- * On the same principle of not depending on previous remote storage,
- * forget the mintuple if it's not local storage. (If it is local
- * storage, we must not pfree it now, since callers might have already
- * fetched datum pointers referencing it.)
- */
- if (!TTS_SHOULDFREEMIN(slot))
- slot->tts_mintuple = NULL;
+ ExecClearTuple(slot);
+ slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+ slot->tts_flags &= ~TTS_FLAG_EMPTY;
+ oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+ bslot->base.tuple = heap_copytuple(tuple);
+ MemoryContextSwitchTo(oldContext);
+ }
+ else
+ {
+ ExecClearTuple(slot);
+ heap_deform_tuple(tuple, slot->tts_tupleDescriptor,
+ slot->tts_values, slot->tts_isnull);
+ ExecStoreVirtualTuple(slot);
+ }
}
-/* --------------------------------
- * ExecCopySlot
- * Copy the source slot's contents into the destination slot.
- *
- * The destination acquires a private copy that will not go away
- * if the source is cleared.
- *
- * The caller must ensure the slots have compatible tupdescs.
- * --------------------------------
- */
-TupleTableSlot *
-ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+void
+ExecForceStoreMinimalTuple(MinimalTuple mtup,
+ TupleTableSlot *slot,
+ bool shouldFree)
{
- HeapTuple newTuple;
- MemoryContext oldContext;
+ if (TTS_IS_MINIMALTUPLE(slot))
+ {
+ tts_minimal_store_tuple(slot, mtup, shouldFree);
+ }
+ else
+ {
+ HeapTupleData htup;
- /*
- * There might be ways to optimize this when the source is virtual, but
- * for now just always build a physical copy. Make sure it is in the
- * right context.
- */
- oldContext = MemoryContextSwitchTo(dstslot->tts_mcxt);
- newTuple = ExecCopySlotTuple(srcslot);
- MemoryContextSwitchTo(oldContext);
+ ExecClearTuple(slot);
- return ExecStoreHeapTuple(newTuple, dstslot, true);
+ htup.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
+ htup.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
+ heap_deform_tuple(&htup, slot->tts_tupleDescriptor,
+ slot->tts_values, slot->tts_isnull);
+ ExecStoreVirtualTuple(slot);
+ }
}
-
/* ----------------------------------------------------------------
* convenience initialization routines
* ----------------------------------------------------------------
@@ -1062,7 +1803,6 @@ void
slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
{
AttrMissing *attrmiss = NULL;
- int missattnum;
if (slot->tts_tupleDescriptor->constr)
attrmiss = slot->tts_tupleDescriptor->constr->missing;
@@ -1077,6 +1817,8 @@ slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
}
else
{
+ int missattnum;
+
/* if there is a missing values array we must process them one by one */
for (missattnum = startAttNum;
missattnum < lastAttNum;
@@ -1085,143 +1827,36 @@ slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
slot->tts_values[missattnum] = attrmiss[missattnum].am_value;
slot->tts_isnull[missattnum] = !attrmiss[missattnum].am_present;
}
+
}
}
/*
- * slot_getattr
- * This function fetches an attribute of the slot's current tuple.
- * It is functionally equivalent to heap_getattr, but fetches of
- * multiple attributes of the same tuple will be optimized better,
- * because we avoid O(N^2) behavior from multiple calls of
- * nocachegetattr(), even when attcacheoff isn't usable.
+ * slot_getsomeattrs_int
*
- * A difference from raw heap_getattr is that attnums beyond the
- * slot's tupdesc's last attribute will be considered NULL even
- * when the physical tuple is longer than the tupdesc.
- */
-Datum
-slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
-{
- HeapTuple tuple = slot->tts_tuple;
- TupleDesc tupleDesc = slot->tts_tupleDescriptor;
- HeapTupleHeader tup;
-
- /*
- * system attributes are handled by heap_getsysattr
- */
- if (attnum <= 0)
- {
- if (tuple == NULL) /* internal error */
- elog(ERROR, "cannot extract system attribute from virtual tuple");
- if (tuple == &(slot->tts_minhdr)) /* internal error */
- elog(ERROR, "cannot extract system attribute from minimal tuple");
- return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
- }
-
- /*
- * fast path if desired attribute already cached
- */
- if (attnum <= slot->tts_nvalid)
- {
- *isnull = slot->tts_isnull[attnum - 1];
- return slot->tts_values[attnum - 1];
- }
-
- /*
- * return NULL if attnum is out of range according to the tupdesc
- */
- if (attnum > tupleDesc->natts)
- {
- *isnull = true;
- return (Datum) 0;
- }
-
- /*
- * otherwise we had better have a physical tuple (tts_nvalid should equal
- * natts in all virtual-tuple cases)
- */
- if (tuple == NULL) /* internal error */
- elog(ERROR, "cannot extract attribute from empty tuple slot");
-
- /*
- * return NULL or missing value if attnum is out of range according to the
- * tuple
- *
- * (We have to check this separately because of various inheritance and
- * table-alteration scenarios: the tuple could be either longer or shorter
- * than the tupdesc.)
- */
- tup = tuple->t_data;
- if (attnum > HeapTupleHeaderGetNatts(tup))
- return getmissingattr(slot->tts_tupleDescriptor, attnum, isnull);
-
- /*
- * check if target attribute is null: no point in groveling through tuple
- */
- if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
- {
- *isnull = true;
- return (Datum) 0;
- }
-
- /*
- * Extract the attribute, along with any preceding attributes.
- */
- slot_deform_tuple(slot, attnum);
-
- /*
- * The result is acquired from tts_values array.
- */
- *isnull = slot->tts_isnull[attnum - 1];
- return slot->tts_values[attnum - 1];
-}
-
-/*
- * slot_getsomeattrs
- * This function forces the entries of the slot's Datum/isnull
- * arrays to be valid at least up through the attnum'th entry.
*/
void
-slot_getsomeattrs(TupleTableSlot *slot, int attnum)
+slot_getsomeattrs_int(TupleTableSlot *slot, int attnum)
{
- HeapTuple tuple;
- int attno;
+ /* Check for caller errors */
+ Assert(slot->tts_nvalid < attnum); /* slot_getsomeattr checked */
+ Assert(attnum > 0);
- /* Quick out if we have 'em all already */
- if (slot->tts_nvalid >= attnum)
- return;
-
- /* Check for caller error */
- if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
+ if (unlikely(attnum > slot->tts_tupleDescriptor->natts))
elog(ERROR, "invalid attribute number %d", attnum);
- /*
- * otherwise we had better have a physical tuple (tts_nvalid should equal
- * natts in all virtual-tuple cases)
- */
- tuple = slot->tts_tuple;
- if (tuple == NULL) /* internal error */
- elog(ERROR, "cannot extract attribute from empty tuple slot");
+ /* Fetch as many attributes as possible from the underlying tuple. */
+ slot->tts_cb->getsomeattrs(slot, attnum);
/*
- * load up any slots available from physical tuple
+ * If the underlying tuple doesn't have enough attributes, tuple descriptor
+ * must have the missing attributes.
*/
- attno = HeapTupleHeaderGetNatts(tuple->t_data);
- attno = Min(attno, attnum);
-
- slot_deform_tuple(slot, attno);
-
- attno = slot->tts_nvalid;
-
- /*
- * If tuple doesn't have all the atts indicated by attnum, read the rest
- * as NULLs or missing values
- */
- if (attno < attnum)
- slot_getmissingattrs(slot, attno, attnum);
-
- slot->tts_nvalid = attnum;
+ if (unlikely(slot->tts_nvalid < attnum))
+ {
+ slot_getmissingattrs(slot, slot->tts_nvalid, attnum);
+ slot->tts_nvalid = attnum;
+ }
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 20d6d8e9cbb..2a1a6123d3b 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1800,9 +1800,8 @@ agg_retrieve_direct(AggState *aggstate)
* reserved for it. The tuple will be deleted when it is
* cleared from the slot.
*/
- ExecStoreHeapTuple(aggstate->grp_firstTuple,
- firstSlot,
- true);
+ ExecForceStoreHeapTuple(aggstate->grp_firstTuple,
+ firstSlot);
aggstate->grp_firstTuple = NULL; /* don't keep two pointers */
/* set up for first advance_aggregates call */
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index d9afd0bdded..8fb477f45c3 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -929,9 +929,10 @@ ExecParallelHashJoinOuterGetTuple(PlanState *outerNode,
hashvalue);
if (tuple != NULL)
{
- slot = ExecStoreMinimalTuple(tuple,
- hjstate->hj_OuterTupleSlot,
- false);
+ ExecForceStoreMinimalTuple(tuple,
+ hjstate->hj_OuterTupleSlot,
+ false);
+ slot = hjstate->hj_OuterTupleSlot;
return slot;
}
else
@@ -1158,9 +1159,10 @@ ExecParallelHashJoinNewBatch(HashJoinState *hjstate)
while ((tuple = sts_parallel_scan_next(inner_tuples,
&hashvalue)))
{
- slot = ExecStoreMinimalTuple(tuple,
- hjstate->hj_HashTupleSlot,
- false);
+ ExecForceStoreMinimalTuple(tuple,
+ hjstate->hj_HashTupleSlot,
+ false);
+ slot = hjstate->hj_HashTupleSlot;
ExecParallelHashTableInsertCurrentBatch(hashtable, slot,
hashvalue);
}
@@ -1294,7 +1296,8 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not read from hash-join temporary file: %m")));
- return ExecStoreMinimalTuple(tuple, tupleSlot, true);
+ ExecForceStoreMinimalTuple(tuple, tupleSlot, true);
+ return tupleSlot;
}
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 9cc499d6533..d29162bab79 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -2059,6 +2059,15 @@ ExecModifyTable(PlanState *pstate)
break;
}
+ /*
+ * Ensure input tuple is the right format for the target relation.
+ */
+ if (node->mt_scans[node->mt_whichplan]->tts_cb != planSlot->tts_cb)
+ {
+ ExecCopySlot(node->mt_scans[node->mt_whichplan], planSlot);
+ planSlot = node->mt_scans[node->mt_whichplan];
+ }
+
/*
* If resultRelInfo->ri_usesFdwDirectModify is true, all we need to do
* here is compute the RETURNING expressions.
@@ -2242,6 +2251,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);
mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;
+ mtstate->mt_scans = (TupleTableSlot **) palloc0(sizeof(TupleTableSlot *) * nplans);
/* If modifying a partitioned table, initialize the root table info */
if (node->rootResultRelIndex >= 0)
@@ -2308,6 +2318,9 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/* Now init the plan for this result rel */
estate->es_result_relation_info = resultRelInfo;
mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);
+ mtstate->mt_scans[i] =
+ ExecInitExtraTupleSlot(mtstate->ps.state, ExecGetResultType(mtstate->mt_plans[i]),
+ &TTSOpsHeapTuple);
/* Also let FDWs init themselves for foreign-table result rels */
if (!resultRelInfo->ri_usesFdwDirectModify &&
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 62811ed0302..b42e60576e3 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -988,6 +988,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
* across-type comparison).
*/
sstate->cur_eq_comp = ExecBuildGroupingEqual(tupDescLeft, tupDescRight,
+ &TTSOpsVirtual, &TTSOpsMinimalTuple,
ncols,
sstate->keyColIdx,
sstate->tab_eq_funcoids,
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 168072afd2f..162d1be89bd 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -65,6 +65,8 @@ LLVMTypeRef StructFormPgAttribute;
LLVMTypeRef StructTupleConstr;
LLVMTypeRef StructtupleDesc;
LLVMTypeRef StructTupleTableSlot;
+LLVMTypeRef StructHeapTupleTableSlot;
+LLVMTypeRef StructMinimalTupleTableSlot;
LLVMTypeRef StructMemoryContextData;
LLVMTypeRef StructPGFinfoRecord;
LLVMTypeRef StructFmgrInfo;
@@ -79,7 +81,7 @@ LLVMTypeRef StructAggStatePerTransData;
LLVMValueRef AttributeTemplate;
LLVMValueRef FuncStrlen;
LLVMValueRef FuncVarsizeAny;
-LLVMValueRef FuncSlotGetsomeattrs;
+LLVMValueRef FuncSlotGetsomeattrsInt;
LLVMValueRef FuncSlotGetmissingattrs;
LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal;
LLVMValueRef FuncExecEvalArrayRefSubscript;
@@ -811,6 +813,8 @@ llvm_create_types(void)
StructFunctionCallInfoData = load_type(mod, "StructFunctionCallInfoData");
StructMemoryContextData = load_type(mod, "StructMemoryContextData");
StructTupleTableSlot = load_type(mod, "StructTupleTableSlot");
+ StructHeapTupleTableSlot = load_type(mod, "StructHeapTupleTableSlot");
+ StructMinimalTupleTableSlot = load_type(mod, "StructMinimalTupleTableSlot");
StructHeapTupleData = load_type(mod, "StructHeapTupleData");
StructtupleDesc = load_type(mod, "StructtupleDesc");
StructAggState = load_type(mod, "StructAggState");
@@ -820,7 +824,7 @@ llvm_create_types(void)
AttributeTemplate = LLVMGetNamedFunction(mod, "AttributeTemplate");
FuncStrlen = LLVMGetNamedFunction(mod, "strlen");
FuncVarsizeAny = LLVMGetNamedFunction(mod, "varsize_any");
- FuncSlotGetsomeattrs = LLVMGetNamedFunction(mod, "slot_getsomeattrs");
+ FuncSlotGetsomeattrsInt = LLVMGetNamedFunction(mod, "slot_getsomeattrs_int");
FuncSlotGetmissingattrs = LLVMGetNamedFunction(mod, "slot_getmissingattrs");
FuncMakeExpandedObjectReadOnlyInternal = LLVMGetNamedFunction(mod, "MakeExpandedObjectReadOnlyInternal");
FuncExecEvalArrayRefSubscript = LLVMGetNamedFunction(mod, "ExecEvalArrayRefSubscript");
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index 59e38d2d955..e430cd9eda4 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -31,7 +31,7 @@
* Create a function that deforms a tuple of type desc up to natts columns.
*/
LLVMValueRef
-slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
+slot_compile_deform(LLVMJitContext *context, TupleDesc desc, const TupleTableSlotOps *ops, int natts)
{
char *funcname;
@@ -88,6 +88,16 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
int attnum;
+ if (ops != &TTSOpsHeapTuple && ops != &TTSOpsBufferTuple &&
+ ops != &TTSOpsMinimalTuple)
+ {
+ /*
+ * Decline to JIT for slot types we don't know to handle, or don't
+ * want to handle (say virtual slots).
+ */
+ return NULL;
+ }
+
mod = llvm_mutable_module(context);
funcname = llvm_expand_funcname(context, "deform");
@@ -166,14 +176,44 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
v_tts_nulls =
l_load_struct_gep(b, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
"tts_ISNULL");
-
- v_slotoffp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_OFF, "");
v_flagsp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
v_nvalidp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
- v_tupleheaderp =
- l_load_struct_gep(b, v_slot, FIELDNO_TUPLETABLESLOT_TUPLE,
- "tupleheader");
+ if (ops == &TTSOpsHeapTuple || ops == &TTSOpsBufferTuple)
+ {
+ LLVMValueRef v_heapslot;
+
+ v_heapslot =
+ LLVMBuildBitCast(b,
+ v_slot,
+ l_ptr(StructHeapTupleTableSlot),
+ "heapslot");
+ v_slotoffp = LLVMBuildStructGEP(b, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
+ v_tupleheaderp =
+ l_load_struct_gep(b, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
+ "tupleheader");
+
+ }
+ else if (ops == &TTSOpsMinimalTuple)
+ {
+ LLVMValueRef v_minimalslot;
+
+ v_minimalslot =
+ LLVMBuildBitCast(b,
+ v_slot,
+ l_ptr(StructMinimalTupleTableSlot),
+ "minimalslotslot");
+ v_slotoffp = LLVMBuildStructGEP(b, v_minimalslot, FIELDNO_MINIMALTUPLETABLESLOT_OFF, "");
+ v_tupleheaderp =
+ l_load_struct_gep(b, v_minimalslot, FIELDNO_MINIMALTUPLETABLESLOT_TUPLE,
+ "tupleheader");
+ }
+ else
+ {
+ /* should've returned at the start of the function */
+ pg_unreachable();
+ }
+
v_tuplep =
l_load_struct_gep(b, v_tupleheaderp, FIELDNO_HEAPTUPLEDATA_DATA,
"tuple");
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 63b921517c6..f3414ef9caf 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -324,6 +324,7 @@ llvm_compile_expr(ExprState *state)
{
l_jit_deform =
slot_compile_deform(context, desc,
+ tts_cb,
op->d.fetch.last_var);
}
@@ -344,7 +345,7 @@ llvm_compile_expr(ExprState *state)
params[1] = l_int32_const(op->d.fetch.last_var);
LLVMBuildCall(b,
- llvm_get_decl(mod, FuncSlotGetsomeattrs),
+ llvm_get_decl(mod, FuncSlotGetsomeattrsInt),
params, lengthof(params), "");
}
diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c
index 855a6977ee5..2df1882b750 100644
--- a/src/backend/jit/llvm/llvmjit_types.c
+++ b/src/backend/jit/llvm/llvmjit_types.c
@@ -59,6 +59,8 @@ FunctionCallInfoData StructFunctionCallInfoData;
HeapTupleData StructHeapTupleData;
MemoryContextData StructMemoryContextData;
TupleTableSlot StructTupleTableSlot;
+HeapTupleTableSlot StructHeapTupleTableSlot;
+MinimalTupleTableSlot StructMinimalTupleTableSlot;
struct tupleDesc StructtupleDesc;
@@ -97,7 +99,7 @@ void *referenced_functions[] =
{
strlen,
varsize_any,
- slot_getsomeattrs,
+ slot_getsomeattrs_int,
slot_getmissingattrs,
MakeExpandedObjectReadOnlyInternal,
ExecEvalArrayRefSubscript,
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
index 97d240fdbb0..1867a70f6f3 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -835,7 +835,5 @@ extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup);
extern size_t varsize_any(void *p);
extern HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
extern MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
-struct TupleTableSlot;
-extern void slot_deform_tuple(struct TupleTableSlot *slot, int natts);
#endif /* HTUP_DETAILS_H */
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 4f156f4a5e7..8b48a23d13e 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -249,6 +249,7 @@ extern List *ExecInitExprList(List *nodes, PlanState *parent);
extern ExprState *ExecBuildAggTrans(AggState *aggstate, struct AggStatePerPhaseData *phase,
bool doSort, bool doHash);
extern ExprState *ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
+ const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
int numCols,
AttrNumber *keyColIdx,
Oid *eqfunctions,
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index a6f6084f0a9..f78853488a9 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -65,7 +65,7 @@
* ie, only as needed. This serves to avoid repeated extraction of data
* from the physical tuple.
*
- * A TupleTableSlot can also be "empty", indicated by flag TTS_EMPTY set in
+ * A TupleTableSlot can also be "empty", indicated by flag TTS_FLAG_EMPTY set in
* tts_flags, holding no valid data. This is the only valid state for a
* freshly-created slot that has not yet had a tuple descriptor assigned to it.
* In this state, TTS_SHOULDFREE should not be set in tts_flag, tts_tuple must
@@ -116,25 +116,22 @@
#define TTS_FLAG_EMPTY (1 << 1)
#define TTS_EMPTY(slot) (((slot)->tts_flags & TTS_FLAG_EMPTY) != 0)
-/* should pfree tts_tuple? */
+/* should pfree tuple "owned" by the slot? */
#define TTS_FLAG_SHOULDFREE (1 << 2)
#define TTS_SHOULDFREE(slot) (((slot)->tts_flags & TTS_FLAG_SHOULDFREE) != 0)
-/* should pfree tts_mintuple? */
-#define TTS_FLAG_SHOULDFREEMIN (1 << 3)
-#define TTS_SHOULDFREEMIN(slot) (((slot)->tts_flags & TTS_FLAG_SHOULDFREEMIN) != 0)
-
/* saved state for slot_deform_tuple */
-#define TTS_FLAG_SLOW (1 << 4)
+#define TTS_FLAG_SLOW (1 << 3)
#define TTS_SLOW(slot) (((slot)->tts_flags & TTS_FLAG_SLOW) != 0)
/* fixed tuple descriptor */
-#define TTS_FLAG_FIXED (1 << 5)
+#define TTS_FLAG_FIXED (1 << 4)
#define TTS_FIXED(slot) (((slot)->tts_flags & TTS_FLAG_FIXED) != 0)
struct TupleTableSlotOps;
typedef struct TupleTableSlotOps TupleTableSlotOps;
+/* virtual or base type */
typedef struct TupleTableSlot
{
NodeTag type;
@@ -142,26 +139,98 @@ typedef struct TupleTableSlot
uint16 tts_flags; /* Boolean states */
#define FIELDNO_TUPLETABLESLOT_NVALID 2
AttrNumber tts_nvalid; /* # of valid values in tts_values */
-#define FIELDNO_TUPLETABLESLOT_TUPLE 3
- HeapTuple tts_tuple; /* physical tuple, or NULL if virtual */
const TupleTableSlotOps *const tts_cb; /* implementation of slot */
-#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 5
+#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
TupleDesc tts_tupleDescriptor; /* slot's tuple descriptor */
- MemoryContext tts_mcxt; /* slot itself is in this context */
- Buffer tts_buffer; /* tuple's buffer, or InvalidBuffer */
-#define FIELDNO_TUPLETABLESLOT_OFF 8
- uint32 tts_off; /* saved state for slot_deform_tuple */
-#define FIELDNO_TUPLETABLESLOT_VALUES 9
+#define FIELDNO_TUPLETABLESLOT_VALUES 5
Datum *tts_values; /* current per-attribute values */
-#define FIELDNO_TUPLETABLESLOT_ISNULL 10
+#define FIELDNO_TUPLETABLESLOT_ISNULL 6
bool *tts_isnull; /* current per-attribute isnull flags */
- MinimalTuple tts_mintuple; /* minimal tuple, or NULL if none */
- HeapTupleData tts_minhdr; /* workspace for minimal-tuple-only case */
+ MemoryContext tts_mcxt; /* slot itself is in this context */
} TupleTableSlot;
/* routines for a TupleTableSlot implementation */
struct TupleTableSlotOps
{
+ /* Minimum size of the slot */
+ size_t base_slot_size;
+
+ /* Initialization. */
+ void (*init)(TupleTableSlot *slot);
+
+ /* Destruction. */
+ void (*release)(TupleTableSlot *slot);
+
+ /*
+ * Clear the contents of the slot. Only the contents are expected to be
+ * cleared and not the tuple descriptor. Typically an implementation of
+ * this callback should free the memory allocated for the tuple contained
+ * in the slot.
+ */
+ void (*clear)(TupleTableSlot *slot);
+
+ /*
+ * Fill up first natts entries of tts_values and tts_isnull arrays with
+ * values from the tuple contained in the slot. The function may be called
+ * with natts more than the number of attributes available in the tuple,
+ * in which case it should set tts_nvalid to the number of returned
+ * columns.
+ */
+ void (*getsomeattrs)(TupleTableSlot *slot, int natts);
+
+ /*
+ * Returns value of the given system attribute as a datum and sets isnull
+ * to false, if it's not NULL. Throws an error if the slot type does not
+ * support system attributes.
+ */
+ Datum (*getsysattr)(TupleTableSlot *slot, int attnum, bool *isnull);
+
+ /*
+ * Make the contents of the slot solely depend on the slot, and not on
+ * underlying resources (like another memory context, buffers, etc).
+ */
+ void (*materialize)(TupleTableSlot *slot);
+
+ /*
+ * Copy the contents of the source slot into the destination slot's own
+ * context. Invoked using callback of the destination slot.
+ */
+ void (*copyslot) (TupleTableSlot *dstslot, TupleTableSlot *srcslot);
+
+ /*
+ * Return a heap tuple "owned" by the slot. It is slot's responsibility to
+ * free the memory consumed by the heap tuple. If the slot can not "own" a
+ * heap tuple, it should not implement this callback and should set it as
+ * NULL.
+ */
+ HeapTuple (*get_heap_tuple)(TupleTableSlot *slot);
+
+ /*
+ * Return a minimal tuple "owned" by the slot. It is slot's responsibility
+ * to free the memory consumed by the minimal tuple. If the slot can not
+ * "own" a minimal tuple, it should not implement this callback and should
+ * set it as NULL.
+ */
+ MinimalTuple (*get_minimal_tuple)(TupleTableSlot *slot);
+
+ /*
+ * Return a copy of heap tuple representing the contents of the slot. The
+ * returned heap tuple should be writable. The copy should be palloc'd in
+ * the current memory context. The slot itself is expected to remain
+ * undisturbed. It is *not* expected to have meaningful "system columns"
+ * in the copy. The copy is not be "owned" by the slot i.e. the caller has
+ * to take responsibilty to free memory consumed by the slot.
+ */
+ HeapTuple (*copy_heap_tuple)(TupleTableSlot *slot);
+
+ /*
+ * Return a copy of minimal tuple representing the contents of the slot.
+ * The returned minimal tuple should be writable. The copy should be
+ * palloc'd in the current memory context. The slot itself is expected to
+ * remain undisturbed. The copy is not be "owned" by the slot i.e. the
+ * caller has to take responsibilty to free memory consumed by the slot.
+ */
+ MinimalTuple (*copy_minimal_tuple)(TupleTableSlot *slot);
};
/*
@@ -173,8 +242,44 @@ extern PGDLLIMPORT const TupleTableSlotOps TTSOpsHeapTuple;
extern PGDLLIMPORT const TupleTableSlotOps TTSOpsMinimalTuple;
extern PGDLLIMPORT const TupleTableSlotOps TTSOpsBufferTuple;
-#define TTS_HAS_PHYSICAL_TUPLE(slot) \
- ((slot)->tts_tuple != NULL && (slot)->tts_tuple != &((slot)->tts_minhdr))
+#define TTS_IS_VIRTUAL(slot) ((slot)->tts_cb == &TTSOpsVirtual)
+#define TTS_IS_HEAPTUPLE(slot) ((slot)->tts_cb == &TTSOpsHeapTuple)
+#define TTS_IS_MINIMALTUPLE(slot) ((slot)->tts_cb == &TTSOpsMinimalTuple)
+#define TTS_IS_BUFFERTUPLE(slot) ((slot)->tts_cb == &TTSOpsBufferTuple)
+
+
+typedef struct VirtualTupleTableSlot
+{
+ TupleTableSlot base;
+ char *data; /* data for materialized slots */
+} VirtualTupleTableSlot;
+
+typedef struct HeapTupleTableSlot
+{
+ TupleTableSlot base;
+#define FIELDNO_HEAPTUPLETABLESLOT_TUPLE 1
+ HeapTuple tuple; /* physical tuple */
+#define FIELDNO_HEAPTUPLETABLESLOT_OFF 2
+ uint32 off; /* saved state for slot_deform_tuple */
+} HeapTupleTableSlot;
+
+/* heap tuple residing in a buffer */
+typedef struct BufferHeapTupleTableSlot
+{
+ HeapTupleTableSlot base;
+ Buffer buffer; /* tuple's buffer, or InvalidBuffer */
+} BufferHeapTupleTableSlot;
+
+typedef struct MinimalTupleTableSlot
+{
+ TupleTableSlot base;
+#define FIELDNO_MINIMALTUPLETABLESLOT_TUPLE 1
+ HeapTuple tuple; /* tuple wrapper */
+ MinimalTuple mintuple; /* minimal tuple, or NULL if none */
+ HeapTupleData minhdr; /* workspace for minimal-tuple-only case */
+#define FIELDNO_MINIMALTUPLETABLESLOT_OFF 4
+ uint32 off; /* saved state for slot_deform_tuple */
+} MinimalTupleTableSlot;
/*
* TupIsNull -- is a TupleTableSlot empty?
@@ -195,39 +300,38 @@ extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
extern TupleTableSlot *ExecStoreHeapTuple(HeapTuple tuple,
TupleTableSlot *slot,
bool shouldFree);
+extern void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot);
extern TupleTableSlot *ExecStoreBufferHeapTuple(HeapTuple tuple,
TupleTableSlot *slot,
Buffer buffer);
extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup,
TupleTableSlot *slot,
bool shouldFree);
-extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot);
+extern void ExecForceStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot,
+ bool shouldFree);
extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot);
extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot);
-extern HeapTuple ExecCopySlotTuple(TupleTableSlot *slot);
-extern MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot);
-extern HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shoulFree);
+extern HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree);
extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
bool *shouldFree);
extern Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot);
-extern void ExecMaterializeSlot(TupleTableSlot *slot);
-extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot,
- TupleTableSlot *srcslot);
extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum,
int lastAttNum);
-extern Datum slot_getattr(TupleTableSlot *slot, int attnum,
- bool *isnull);
-extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum);
-
-/* in access/common/heaptuple.c */
-extern bool slot_attisnull(TupleTableSlot *slot, int attnum);
-extern bool slot_getsysattr(TupleTableSlot *slot, int attnum,
- Datum *value, bool *isnull);
-extern Datum getmissingattr(TupleDesc tupleDesc,
- int attnum, bool *isnull);
+extern void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum);
#ifndef FRONTEND
+/*
+ * This function forces the entries of the slot's Datum/isnull arrays to be
+ * valid at least up through the attnum'th entry.
+ */
+static inline void
+slot_getsomeattrs(TupleTableSlot *slot, int attnum)
+{
+ if (slot->tts_nvalid < attnum)
+ slot_getsomeattrs_int(slot, attnum);
+}
+
/*
* slot_getallattrs
* This function forces all the entries of the slot's Datum/isnull
@@ -240,6 +344,129 @@ slot_getallattrs(TupleTableSlot *slot)
slot_getsomeattrs(slot, slot->tts_tupleDescriptor->natts);
}
-#endif
+
+/*
+ * slot_attisnull
+ *
+ * Detect whether an attribute of the slot is null, without actually fetching
+ * it.
+ */
+static inline bool
+slot_attisnull(TupleTableSlot *slot, int attnum)
+{
+ AssertArg(attnum > 0);
+
+ if (attnum > slot->tts_nvalid)
+ slot_getsomeattrs(slot, attnum);
+
+ return slot->tts_isnull[attnum - 1];
+}
+
+static inline Datum
+slot_getattr(TupleTableSlot *slot, int attnum,
+ bool *isnull)
+{
+ AssertArg(attnum > 0);
+
+ if (attnum > slot->tts_nvalid)
+ slot_getsomeattrs(slot, attnum);
+
+ *isnull = slot->tts_isnull[attnum - 1];
+
+ return slot->tts_values[attnum - 1];
+}
+
+/*
+ * slot_getsysattr
+ * This function fetches a system attribute of the slot's current tuple.
+ * If the slot type does not contain system attributes, this will throw
+ * an error. Hence before calling this function, callers should make sure
+ * that the slot type is the one that supports system attributes, namely,
+ * heap tuple slot and buffer tuple slot.
+ */
+static inline Datum
+slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+ AssertArg(attnum < 0); /* caller error */
+
+ /* Fetch the system attribute from the underlying tuple. */
+ return slot->tts_cb->getsysattr(slot, attnum, isnull);
+}
+
+/*
+ * ExecClearTuple
+ *
+ * A thin wrapper around calling TupleTableSlotType specific clear() method.
+ */
+static inline TupleTableSlot *
+ExecClearTuple(TupleTableSlot *slot)
+{
+ slot->tts_cb->clear(slot);
+
+ return slot;
+}
+
+/* ExecMaterializeSlot - force a slot into the "materialized" state.
+ *
+ * This causes the slot's tuple to be a local copy not dependent on any
+ * external storage (i.e. pointing into a Buffer, or having allocations in
+ * another memory context).
+ *
+ * A typical use for this operation is to prepare a computed tuple for being
+ * stored on disk. The original data may or may not be virtual, but in any
+ * case we need a private copy for heap_insert to scribble on.
+ */
+static inline void
+ExecMaterializeSlot(TupleTableSlot *slot)
+{
+ slot->tts_cb->materialize(slot);
+}
+
+/*
+ * ExecCopySlotTuple
+ *
+ * A thin wrapper calling TupleTableSlotType specific copy_heap_tuple()
+ * method.
+ */
+static inline HeapTuple
+ExecCopySlotTuple(TupleTableSlot *slot)
+{
+ /*
+ * sanity checks
+ */
+ Assert(slot != NULL);
+ Assert(!TTS_EMPTY(slot));
+
+ return slot->tts_cb->copy_heap_tuple(slot);
+}
+
+/*
+ * ExecCopySlotMinimalTuple
+ *
+ * A thin wrapper around calling TupleTableSlotType specific
+ * copy_minimal_tuple() method.
+ */
+static inline MinimalTuple
+ExecCopySlotMinimalTuple(TupleTableSlot *slot)
+{
+ return slot->tts_cb->copy_minimal_tuple(slot);
+}
+
+/*
+ * ExecCopySlot
+ *
+ * A thin wrapper calling TupleTableSlotType specific copyslot callback.
+ *
+ * The caller must ensure the slots have compatible tupdescs.
+ */
+static inline TupleTableSlot *
+ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+ dstslot->tts_cb->copyslot(dstslot, srcslot);
+
+ return dstslot;
+}
+
+#endif /* FRONTEND */
#endif /* TUPTABLE_H */
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index f3ea2492835..b4b0a16d1ae 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -65,6 +65,8 @@ extern LLVMTypeRef TypeStorageBool;
extern LLVMTypeRef StructtupleDesc;
extern LLVMTypeRef StructHeapTupleData;
extern LLVMTypeRef StructTupleTableSlot;
+extern LLVMTypeRef StructHeapTupleTableSlot;
+extern LLVMTypeRef StructMinimalTupleTableSlot;
extern LLVMTypeRef StructMemoryContextData;
extern LLVMTypeRef StructFunctionCallInfoData;
extern LLVMTypeRef StructExprContext;
@@ -77,7 +79,7 @@ extern LLVMTypeRef StructAggStatePerGroupData;
extern LLVMValueRef AttributeTemplate;
extern LLVMValueRef FuncStrlen;
extern LLVMValueRef FuncVarsizeAny;
-extern LLVMValueRef FuncSlotGetsomeattrs;
+extern LLVMValueRef FuncSlotGetsomeattrsInt;
extern LLVMValueRef FuncSlotGetmissingattrs;
extern LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal;
extern LLVMValueRef FuncExecEvalArrayRefSubscript;
@@ -111,7 +113,8 @@ extern void llvm_inline(LLVMModuleRef mod);
****************************************************************************
*/
extern bool llvm_compile_expr(struct ExprState *state);
-extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDesc desc, int natts);
+struct TupleTableSlotOps;
+extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDesc desc, const struct TupleTableSlotOps *ops, int natts);
/*
****************************************************************************
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 59fb3c15833..149916093a2 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1100,6 +1100,7 @@ typedef struct ModifyTableState
PlanState **mt_plans; /* subplans (one per target rel) */
int mt_nplans; /* number of plans in the array */
int mt_whichplan; /* which one is being executed (0..n-1) */
+ TupleTableSlot** mt_scans; /* input tuple for underlying plan */
ResultRelInfo *resultRelInfo; /* per-subplan target relations */
ResultRelInfo *rootResultRelInfo; /* root target relation (partitioned
* table root) */
--
2.18.0.rc2.dirty
--ll5lqoiis2grgqzk
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v14-0007-Rationalize-expression-context-reset-in-ExecModi.patch"
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v2 1/4] Make stack depth check work with asan's use-after-return
@ 2026-02-07 19:04 Andres Freund <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Andres Freund @ 2026-02-07 19:04 UTC (permalink / raw)
With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
.cirrus.tasks.yml | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
bool
stack_is_too_deep(void)
{
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
char stack_top_loc;
+#endif
ssize_t stack_depth;
+ char *stack_address;
+
+ /*
+ * With address sanitizer's stack-use-after-return check, stack variables
+ * are moved to heap allocations, to allow to detect references to the
+ * memory at a later time. That would break our stack-depth check. Luckily
+ * __builtin_frame_address() works correctly, even under asan.
+ */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+ stack_address = &stack_top_loc;
+#else
+ stack_address = (char *) __builtin_frame_address(0);
+#endif
/*
* Compute distance from reference point to my local variables
*/
- stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+ stack_depth = (ssize_t) (stack_base_ptr - stack_address);
/*
* Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
# print_stacktraces=1,verbosity=2, duh
# detect_leaks=0: too many uninteresting leak errors in short-lived binaries
UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
- ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+ ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
# SANITIZER_FLAGS is set in the tasks below
CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
--
2.53.0.1.gb2826b52eb
--7e2sypi5gxvkgog6--
^ permalink raw reply [nested|flat] 114+ messages in thread
* [PATCH v6] contrib/sslinfo: Add ssl_group_info
@ 2026-05-13 17:51 Dmitrii Dolgov <[email protected]>
0 siblings, 0 replies; 114+ messages in thread
From: Dmitrii Dolgov @ 2026-05-13 17:51 UTC (permalink / raw)
Add a new function to sslinfo ssl_group_info to show SSL groups,
including negotiated, supported and shared. It's useful for diagnostic
purposes, to identify what's being used and supported, e.g. which key
share is being negotiated. Few examples, for openssl 3.2.4:
select * from ssl_group_info();
type | name
------------+--------------------
negotiated | X25519MLKEM768
shared | X25519MLKEM768
shared | x25519
supported | X25519MLKEM768
supported | x25519
[...]
The implementation is inspired by ssl_print_groups from openssl.
Reviewed-by: Daniel Gustafsson <[email protected]>
Reviewed-by: Jacob Champion <[email protected]>
Reviewed-by: Cary Huang <[email protected]>
Reviewed-by: Zsolt Parragi <[email protected]>
---
configure | 36 +++++
configure.ac | 4 +
contrib/sslinfo/Makefile | 2 +-
contrib/sslinfo/meson.build | 1 +
contrib/sslinfo/sslinfo--1.2--1.3.sql | 10 ++
contrib/sslinfo/sslinfo.c | 192 +++++++++++++++++++++++++-
contrib/sslinfo/sslinfo.control | 2 +-
doc/src/sgml/sslinfo.sgml | 45 ++++++
meson.build | 5 +
src/include/pg_config.h.in | 11 ++
src/tools/pgindent/typedefs.list | 1 +
11 files changed, 306 insertions(+), 3 deletions(-)
create mode 100644 contrib/sslinfo/sslinfo--1.2--1.3.sql
diff --git a/configure b/configure
index f66c1054a7a..2a708df5afd 100755
--- a/configure
+++ b/configure
@@ -13189,6 +13189,42 @@ _ACEOF
fi
done
+ # Functions for groups support, some of them are real functions, some are
+ # just wrappers around SSL_ctrl.
+ for ac_func in SSL_group_to_name
+do :
+ ac_fn_c_check_func "$LINENO" "SSL_group_to_name" "ac_cv_func_SSL_group_to_name"
+if test "x$ac_cv_func_SSL_group_to_name" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SSL_GROUP_TO_NAME 1
+_ACEOF
+
+fi
+done
+
+ac_fn_c_check_decl "$LINENO" "SSL_get1_groups" "ac_cv_have_decl_SSL_get1_groups" "#include <openssl/ssl.h>
+"
+if test "x$ac_cv_have_decl_SSL_get1_groups" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SSL_GET1_GROUPS $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "SSL_get_negotiated_group" "ac_cv_have_decl_SSL_get_negotiated_group" "#include <openssl/ssl.h>
+"
+if test "x$ac_cv_have_decl_SSL_get_negotiated_group" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SSL_GET_NEGOTIATED_GROUP $ac_have_decl
+_ACEOF
+
$as_echo "#define USE_OPENSSL 1" >>confdefs.h
diff --git a/configure.ac b/configure.ac
index 8d176bd3468..2641a17d317 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1444,6 +1444,10 @@ if test "$with_ssl" = openssl ; then
AC_CHECK_FUNCS([SSL_CTX_set_cert_cb])
# Function introduced in OpenSSL 1.1.1, not in LibreSSL.
AC_CHECK_FUNCS([X509_get_signature_info SSL_CTX_set_num_tickets SSL_CTX_set_keylog_callback SSL_CTX_set_client_hello_cb])
+ # Functions for groups support, some of them are real functions, some are
+ # just wrappers around SSL_ctrl.
+ AC_CHECK_FUNCS([SSL_group_to_name])
+ AC_CHECK_DECLS([SSL_get1_groups, SSL_get_negotiated_group], [], [], [#include <openssl/ssl.h>])
AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)])
elif test "$with_ssl" != no ; then
AC_MSG_ERROR([--with-ssl must specify openssl])
diff --git a/contrib/sslinfo/Makefile b/contrib/sslinfo/Makefile
index 14305594e2d..d968ef2abfd 100644
--- a/contrib/sslinfo/Makefile
+++ b/contrib/sslinfo/Makefile
@@ -6,7 +6,7 @@ OBJS = \
sslinfo.o
EXTENSION = sslinfo
-DATA = sslinfo--1.2.sql sslinfo--1.1--1.2.sql sslinfo--1.0--1.1.sql
+DATA = sslinfo--1.2.sql sslinfo--1.2--1.3.sql sslinfo--1.1--1.2.sql sslinfo--1.0--1.1.sql
PGFILEDESC = "sslinfo - information about client SSL certificate"
ifdef USE_PGXS
diff --git a/contrib/sslinfo/meson.build b/contrib/sslinfo/meson.build
index 6e9cb96430a..27737562925 100644
--- a/contrib/sslinfo/meson.build
+++ b/contrib/sslinfo/meson.build
@@ -26,6 +26,7 @@ install_data(
'sslinfo--1.0--1.1.sql',
'sslinfo--1.1--1.2.sql',
'sslinfo--1.2.sql',
+ 'sslinfo--1.2--1.3.sql',
'sslinfo.control',
kwargs: contrib_data_args,
)
diff --git a/contrib/sslinfo/sslinfo--1.2--1.3.sql b/contrib/sslinfo/sslinfo--1.2--1.3.sql
new file mode 100644
index 00000000000..40fd0ea2b9c
--- /dev/null
+++ b/contrib/sslinfo/sslinfo--1.2--1.3.sql
@@ -0,0 +1,10 @@
+/* contrib/sslinfo/sslinfo--1.2--1.3.sql */
+
+-- complain if script is sourced in psql, rather than via ALTER EXTENSION
+\echo Use "ALTER EXTENSION sslinfo UPDATE TO '1.3'" to load this file. \quit
+
+CREATE FUNCTION
+ssl_group_info(OUT group_type text, OUT name text
+) RETURNS SETOF record
+AS 'MODULE_PATHNAME', 'ssl_group_info'
+LANGUAGE C STRICT PARALLEL RESTRICTED;
diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c
index 2b9eb90b093..8807f50c908 100644
--- a/contrib/sslinfo/sslinfo.c
+++ b/contrib/sslinfo/sslinfo.c
@@ -19,6 +19,14 @@
#include "miscadmin.h"
#include "utils/builtins.h"
+#if HAVE_DECL_SSL_GET1_GROUPS && \
+ HAVE_DECL_SSL_GET_NEGOTIATED_GROUP && \
+ defined(HAVE_SSL_GROUP_TO_NAME) \
+
+#define HAVE_SSL_GROUPS
+
+#endif
+
PG_MODULE_MAGIC_EXT(
.name = "sslinfo",
.version = PG_VERSION
@@ -28,13 +36,28 @@ static Datum X509_NAME_field_to_text(X509_NAME *name, text *fieldName);
static Datum ASN1_STRING_to_text(ASN1_STRING *str);
/*
- * Function context for data persisting over repeated calls.
+ * Function context for data persisting over repeated calls of
+ * ssl_extension_info.
*/
typedef struct
{
TupleDesc tupdesc;
} SSLExtensionInfoContext;
+/*
+ * Function context for data persisting over repeated calls of
+ * ssl_group_info.
+ */
+typedef struct
+{
+ TupleDesc tupdesc;
+ int nshared;
+ int nsupported;
+
+ /* Supported groups have to be stored separately */
+ int *supported_groups;
+} SSLGroupInfoContext;
+
/*
* Indicates whether current session uses SSL
*
@@ -474,3 +497,170 @@ ssl_extension_info(PG_FUNCTION_ARGS)
/* All done */
SRF_RETURN_DONE(funcctx);
}
+
+/*
+ * Returns information about TLS groups.
+ *
+ * Returns setof record made of the following values:
+ * - type of the group: negotiated, shared, supported.
+ * - name of the group.
+ */
+PG_FUNCTION_INFO_V1(ssl_group_info);
+Datum
+ssl_group_info(PG_FUNCTION_ARGS)
+{
+#ifdef HAVE_SSL_GROUPS
+ /*
+ * If we lack SSL groups API, we still need to do SRF stuff. Thus the
+ * condition doesn't cover the whole function, but only parts of it. This
+ * particular one is only to avoid unused variable warning, in case if
+ * HAVE_SSL_GROUPS is false.
+ */
+ SSL *ssl = MyProcPort->ssl;
+#endif
+
+ FuncCallContext *funcctx;
+ int call_cntr = 0;
+ int max_calls = 0;
+ MemoryContext oldcontext;
+ SSLGroupInfoContext *fctx;
+
+ if (SRF_IS_FIRSTCALL())
+ {
+
+ TupleDesc tupdesc;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /*
+ * Switch to memory context appropriate for multiple function calls
+ */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ /* Create a user function context for cross-call persistence */
+ fctx = palloc_object(SSLGroupInfoContext);
+
+ /* Construct tuple descriptor */
+ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("function returning record called in context that cannot accept type record")));
+ fctx->tupdesc = BlessTupleDesc(tupdesc);
+
+ if (!MyProcPort->ssl_in_use)
+ {
+ /* fast track when no results */
+ MemoryContextSwitchTo(oldcontext);
+ SRF_RETURN_DONE(funcctx);
+ }
+
+#ifdef HAVE_SSL_GROUPS
+ if (ssl != NULL)
+ {
+ fctx->nsupported = SSL_get1_groups(ssl, NULL);
+ fctx->nshared = SSL_get_shared_group(ssl, -1);
+
+ fctx->supported_groups =
+ palloc(fctx->nsupported * sizeof(*fctx->supported_groups));
+ SSL_get1_groups(ssl, fctx->supported_groups);
+
+ /*
+ * Set max_calls as the number of supported groups plus the number
+ * of shared groups plus one negotiated group.
+ */
+ max_calls = fctx->nsupported + fctx->nshared + 1;
+ }
+
+ if (max_calls > 0)
+ {
+ /* got results, keep track of them */
+ funcctx->max_calls = max_calls;
+ funcctx->user_fctx = fctx;
+ }
+ else
+ {
+ /* fast track when no results */
+ MemoryContextSwitchTo(oldcontext);
+ SRF_RETURN_DONE(funcctx);
+ }
+#else
+ /* SSL groups API is not present, skip */
+ MemoryContextSwitchTo(oldcontext);
+ SRF_RETURN_DONE(funcctx);
+#endif
+
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+
+ /*
+ * Initialize per-call variables.
+ */
+ call_cntr = funcctx->call_cntr;
+ max_calls = funcctx->max_calls;
+ fctx = funcctx->user_fctx;
+
+ /* do while there are more left to send */
+ if (call_cntr < max_calls)
+ {
+#ifdef HAVE_SSL_GROUPS
+ Datum values[2];
+ bool nulls[2];
+ HeapTuple tuple;
+ Datum result,
+ group_type;
+ int nid;
+ const char *group_name;
+
+ /* Send the negotiated group first */
+ if (call_cntr == 0)
+ {
+ nid = SSL_get_negotiated_group(ssl);
+ group_type = CStringGetTextDatum("negotiated");
+ }
+ /* Then the shared groups */
+ else if (call_cntr < fctx->nshared + 1)
+ {
+ nid = SSL_get_shared_group(ssl, call_cntr - 1);
+ group_type = CStringGetTextDatum("shared");
+ }
+ /* And finally the supported groups */
+ else if (call_cntr < fctx->nsupported + fctx->nshared + 1)
+ {
+ nid = fctx->supported_groups[call_cntr - fctx->nshared - 1];
+ group_type = CStringGetTextDatum("supported");
+ }
+ else
+ SRF_RETURN_DONE(funcctx);
+
+ /*
+ * SSL_group_to_name can return NULL in case of an error, e.g. when no
+ * such name was registered for some reason.
+ */
+ group_name = SSL_group_to_name(ssl, nid);
+ if (group_name == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("unknown OpenSSL group at position %d",
+ call_cntr)));
+
+ values[0] = group_type;
+ nulls[0] = false;
+
+ values[1] = CStringGetTextDatum(group_name);
+ nulls[1] = false;
+
+ /* Build tuple */
+ tuple = heap_form_tuple(fctx->tupdesc, values, nulls);
+ result = HeapTupleGetDatum(tuple);
+
+ SRF_RETURN_NEXT(funcctx, result);
+#endif
+ }
+
+ /* All done */
+ SRF_RETURN_DONE(funcctx);
+}
diff --git a/contrib/sslinfo/sslinfo.control b/contrib/sslinfo/sslinfo.control
index c7754f924cf..b53e95b7da8 100644
--- a/contrib/sslinfo/sslinfo.control
+++ b/contrib/sslinfo/sslinfo.control
@@ -1,5 +1,5 @@
# sslinfo extension
comment = 'information about SSL certificates'
-default_version = '1.2'
+default_version = '1.3'
module_pathname = '$libdir/sslinfo'
relocatable = true
diff --git a/doc/src/sgml/sslinfo.sgml b/doc/src/sgml/sslinfo.sgml
index 85d49f66537..34fc187e4e4 100644
--- a/doc/src/sgml/sslinfo.sgml
+++ b/doc/src/sgml/sslinfo.sgml
@@ -240,6 +240,51 @@ emailAddress
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>
+ <function>ssl_group_info() returns setof record</function>
+ <indexterm>
+ <primary>ssl_group_info</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Provide information about TLS groups: group type and group name.
+ The group type value could be one of the following:
+
+ <variablelist>
+ <varlistentry id="ssl-group-info-negotiated">
+ <term><literal>negotiated</literal></term>
+ <listitem>
+ <para>
+ The group used for the handshake key exchange process.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="ssl-group-info-shared">
+ <term><literal>shared</literal></term>
+ <listitem>
+ <para>
+ List of named groups shared with the server side.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="ssl-group-info-supported">
+ <term><literal>supported</literal></term>
+ <listitem>
+ <para>
+ list of named groups supported by the client for key exchange in the
+ form of "supported_groups" extension.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</sect2>
diff --git a/meson.build b/meson.build
index 20b887f1a1b..90e99705656 100644
--- a/meson.build
+++ b/meson.build
@@ -1677,6 +1677,9 @@ if sslopt in ['auto', 'openssl']
['SSL_CTX_set_num_tickets'],
['SSL_CTX_set_keylog_callback'],
['SSL_CTX_set_client_hello_cb'],
+
+ # Function for groups support.
+ ['SSL_group_to_name'],
]
are_openssl_funcs_complete = true
@@ -2901,6 +2904,8 @@ decl_checks = [
['strlcpy', 'string.h'],
['strsep', 'string.h'],
['timingsafe_bcmp', 'string.h'],
+ ['SSL_get1_groups', 'openssl/ssl.h'],
+ ['SSL_get_negotiated_group', 'openssl/ssl.h'],
]
# Need to check for function declarations for these functions, because
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 4f8113c144b..67090821722 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -101,6 +101,14 @@
don't. */
#undef HAVE_DECL_PWRITEV
+/* Define to 1 if you have the declaration of `SSL_get1_groups', and to 0 if
+ you don't. */
+#undef HAVE_DECL_SSL_GET1_GROUPS
+
+/* Define to 1 if you have the declaration of `SSL_get_negotiated_group', and
+ to 0 if you don't. */
+#undef HAVE_DECL_SSL_GET_NEGOTIATED_GROUP
+
/* Define to 1 if you have the declaration of `strchrnul', and to 0 if you
don't. */
#undef HAVE_DECL_STRCHRNUL
@@ -384,6 +392,9 @@
/* Define to 1 if you have the `SSL_CTX_set_num_tickets' function. */
#undef HAVE_SSL_CTX_SET_NUM_TICKETS
+/* Define to 1 if you have the `SSL_group_to_name' function. */
+#undef HAVE_SSL_GROUP_TO_NAME
+
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index cbd9e10fc1d..cb8b4ea306e 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2777,6 +2777,7 @@ SQLValueFunction
SQLValueFunctionOp
SSL
SSLExtensionInfoContext
+SSLGroupInfoContext
SSL_CTX
STARTUPINFO
STRLEN
base-commit: 3bf63730cb041a834c618082ba3d5e8bf96a31a5
--
2.52.0
--vt4heavyb5tqbgln--
^ permalink raw reply [nested|flat] 114+ messages in thread
end of thread, other threads:[~2026-05-13 17:51 UTC | newest]
Thread overview: 114+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2018-11-13 20:58 [PATCH v14 6/7] Restructure TupleTableSlot to allow tuples other than HeapTuple Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-02-07 19:04 [PATCH v2 1/4] Make stack depth check work with asan's use-after-return Andres Freund <[email protected]>
2026-05-13 17:51 [PATCH v6] contrib/sslinfo: Add ssl_group_info Dmitrii Dolgov <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox