diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c index 24019f82893..2756900077c 100644 --- a/contrib/pgcrypto/pgcrypto.c +++ b/contrib/pgcrypto/pgcrypto.c @@ -492,6 +492,7 @@ pg_check_fipsmode(PG_FUNCTION_ARGS) PG_RETURN_BOOL(CheckFIPSMode()); } +pg_attribute_no_sanitize_function() static void * find_provider(text *name, PFN provider_lookup, diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 4207f0e0e08..5c1eaadd442 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -6574,6 +6574,7 @@ heap_abort_speculative(Relation relation, const ItemPointerData *tid) * consequence that the table's next VACUUM could see the table's relfrozenxid * move forward between vacuum_get_cutoffs() and finishing. */ +pg_attribute_no_sanitize_function() bool heap_inplace_lock(Relation relation, HeapTuple oldtup_ptr, Buffer buffer, diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 9512a6a824a..678b9a046ce 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -2099,6 +2099,7 @@ check_functions_in_node(Node *node, check_function_callback checker, * uses, but may need to be revisited in future. */ +pg_attribute_no_sanitize_function() bool expression_tree_walker_impl(Node *node, tree_walker_callback walker, @@ -2704,6 +2705,7 @@ expression_tree_walker_impl(Node *node, * which is the bitwise OR of flag values to add or suppress visitation of * indicated items. (More flag bits may be added as needed.) */ +pg_attribute_no_sanitize_function() bool query_tree_walker_impl(Query *query, tree_walker_callback walker, @@ -2828,6 +2830,7 @@ range_table_walker_impl(List *rtable, /* * Some callers even want to scan the expressions in individual RTEs. */ +pg_attribute_no_sanitize_function() bool range_table_entry_walker_impl(RangeTblEntry *rte, tree_walker_callback walker, @@ -2956,6 +2959,7 @@ range_table_entry_walker_impl(RangeTblEntry *rte, * and doing the right thing. */ +pg_attribute_no_sanitize_function() Node * expression_tree_mutator_impl(Node *node, tree_mutator_callback mutator, @@ -3783,6 +3787,7 @@ expression_tree_mutator_impl(Node *node, * it to be modified in-place; they must pass QTW_DONT_COPY_QUERY in flags. * All modified substructure is safely copied in any case. */ +pg_attribute_no_sanitize_function() Query * query_tree_mutator_impl(Query *query, tree_mutator_callback mutator, @@ -3874,6 +3879,7 @@ query_tree_mutator_impl(Query *query, * a query's rangetable. This is split out since it can be useful on * its own. */ +pg_attribute_no_sanitize_function() List * range_table_mutator_impl(List *rtable, tree_mutator_callback mutator, @@ -3952,6 +3958,7 @@ range_table_mutator_impl(List *rtable, * the recursion when the walker's normal change of state is not appropriate * for the outermost Query node. */ +pg_attribute_no_sanitize_function() bool query_or_expression_tree_walker_impl(Node *node, tree_walker_callback walker, @@ -3975,6 +3982,7 @@ query_or_expression_tree_walker_impl(Node *node, * the recursion when the mutator's normal change of state is not appropriate * for the outermost Query node. */ +pg_attribute_no_sanitize_function() Node * query_or_expression_tree_mutator_impl(Node *node, tree_mutator_callback mutator, @@ -4006,6 +4014,7 @@ query_or_expression_tree_mutator_impl(Node *node, * because this is used mainly during analysis of CTEs, and only DML * statements can appear in CTEs. */ +pg_attribute_no_sanitize_function() bool raw_expression_tree_walker_impl(Node *node, tree_walker_callback walker, @@ -4729,6 +4738,7 @@ raw_expression_tree_walker_impl(Node *node, * The walker has already visited the current node, and so we need only * recurse into any sub-nodes it has. */ +pg_attribute_no_sanitize_function() bool planstate_tree_walker_impl(PlanState *planstate, planstate_tree_walker_callback walker, @@ -4813,6 +4823,7 @@ planstate_tree_walker_impl(PlanState *planstate, /* * Walk a list of SubPlans (or initPlans, which also use SubPlan nodes). */ +pg_attribute_no_sanitize_function() static bool planstate_walk_subplans(List *plans, planstate_tree_walker_callback walker, @@ -4835,6 +4846,7 @@ planstate_walk_subplans(List *plans, * Walk the constituent plans of a ModifyTable, Append, MergeAppend, * BitmapAnd, or BitmapOr node. */ +pg_attribute_no_sanitize_function() static bool planstate_walk_members(PlanState **planstates, int nplans, planstate_tree_walker_callback walker, diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 08f99dff711..2dc81a8d3b2 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -197,6 +197,7 @@ parse_analyze_varparams(RawStmt *parseTree, const char *sourceText, * This variant is used when the caller supplies their own parser callback to * resolve parameters and possibly other things. */ +pg_attribute_no_sanitize_function() Query * parse_analyze_withcb(RawStmt *parseTree, const char *sourceText, ParserSetupHook parserSetup, diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index f6fc6271a2e..0db984a26c0 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -898,6 +898,7 @@ hash_search(HTAB *hashp, foundPtr); } +pg_attribute_no_sanitize_function() void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, @@ -1073,6 +1074,7 @@ hash_search_with_hash_value(HTAB *hashp, * NB: for a partitioned hashtable, caller must hold lock on both relevant * partitions, if the new hash key would belong to a different partition. */ +pg_attribute_no_sanitize_function() bool hash_update_hash_key(HTAB *hashp, void *existingEntry, diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index 594c7a93bba..917cc0ac771 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -633,6 +633,7 @@ MemoryContextUnregisterResetCallback(MemoryContext context, * MemoryContextCallResetCallbacks * Internal function to call all registered callbacks for context. */ +pg_attribute_no_sanitize_function() static void MemoryContextCallResetCallbacks(MemoryContext context) { diff --git a/src/include/c.h b/src/include/c.h index 7a2154ab585..95e71d7e612 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -277,6 +277,22 @@ extern "C++" #define pg_attribute_no_sanitize_alignment() #endif +/* + * Place this macro before functions that intentionally call through a + * function pointer whose type does not exactly match the called function. + * The prime examples are the expression tree walkers and mutators, which are + * declared with their own concrete node and context types and cast to a + * generic signature. That is, strictly speaking, undefined behavior, but it + * is a convenient convention that works in practice. See also + * -Wno-cast-function-type-strict, which disables the corresponding + * compile-time warning. + */ +#ifdef __clang__ +#define pg_attribute_no_sanitize_function() __attribute__((no_sanitize("function"))) +#else +#define pg_attribute_no_sanitize_function() +#endif + /* * pg_attribute_nonnull means the compiler should warn if the function is * called with the listed arguments set to NULL. If no arguments are diff --git a/src/include/executor/execScan.h b/src/include/executor/execScan.h index 25efc622f88..a5902645543 100644 --- a/src/include/executor/execScan.h +++ b/src/include/executor/execScan.h @@ -29,6 +29,7 @@ * eliminated at compile time, avoiding unnecessary run-time checks and code * for cases where EPQ is not required. */ +pg_attribute_no_sanitize_function() static pg_always_inline TupleTableSlot * ExecScanFetch(ScanState *node, EPQState *epqstate, diff --git a/src/include/lib/sort_template.h b/src/include/lib/sort_template.h index 22b2092d03b..960b831d919 100644 --- a/src/include/lib/sort_template.h +++ b/src/include/lib/sort_template.h @@ -257,6 +257,7 @@ ST_SCOPE void ST_SORT(ST_ELEMENT_TYPE * first, size_t n * Refer to the comment at the top of this file for known caveats to consider * when writing inlined comparator functions. */ +pg_attribute_no_sanitize_function() static pg_noinline ST_ELEMENT_TYPE * ST_MED3(ST_ELEMENT_TYPE * a, ST_ELEMENT_TYPE * b, @@ -288,6 +289,7 @@ ST_SWAPN(ST_POINTER_TYPE * a, ST_POINTER_TYPE * b, size_t n) /* * Sort an array. */ +pg_attribute_no_sanitize_function() ST_SCOPE void ST_SORT(ST_ELEMENT_TYPE * data, size_t n ST_SORT_PROTO_ELEMENT_SIZE diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c index 92cd9116c0e..e15962563f5 100644 --- a/src/pl/plpgsql/src/pl_funcs.c +++ b/src/pl/plpgsql/src/pl_funcs.c @@ -360,6 +360,7 @@ typedef void (*plpgsql_expr_walker_callback) (PLpgSQL_expr *expr, plpgsql_statement_tree_walker_impl(s, (plpgsql_stmt_walker_callback) (sw), \ (plpgsql_expr_walker_callback) (ew), c) +pg_attribute_no_sanitize_function() static void plpgsql_statement_tree_walker_impl(PLpgSQL_stmt *stmt, plpgsql_stmt_walker_callback stmt_callback,