On Tue, May 24, 2022 at 11:17:39PM -0700, Andres Freund wrote: > On 2022-05-24 11:41:49 -0700, Nathan Bossart wrote: >> I would actually ERROR on this so that we aren't relying on >> --enable-cassert builds to catch it. > > How about adding pg_nonnull(...) (ending up as __attribute__((nonnull(...))? > Then code passing NULLs would get compiler warnings? It'd be useful in quite a > few more places.
I attached an attempt at this for the "name" and "valueAddr" arguments for the DefineCustomXXXVariable functions. It looked like nonnull was supported by GCC and Clang, but I haven't looked too closely to see whether we need version checks as well. >> That being said, if there's no strong reason to enforce that a short >> description be provided, then why not adjust ShowAllGUCConfig() to set that >> column to NULL when short_desc is missing? > > There's a bunch more places that'd need to be adjusted, if we go that way. I > don't really have an opinion on it. I looked around and didn't see anywhere else obvious that needed adjustment besides what Michael pointed out (3ac7d024). Am I missing something? -- Nathan Bossart Amazon Web Services: https://aws.amazon.com
>From 3c2503a1794d40c515f53e632952d59317015d02 Mon Sep 17 00:00:00 2001 From: Steve Chavez <st...@supabase.io> Date: Tue, 24 May 2022 23:46:40 -0500 Subject: [PATCH v3 1/1] Handle a NULL short_desc in ShowAllGUCConfig Prevent a segfault when using a SHOW ALL, in case a DefineCustomXXXVariable() was defined with a NULL short_desc. --- src/backend/utils/misc/guc.c | 16 +++++++++++++--- src/include/c.h | 10 ++++++++++ src/include/utils/guc.h | 10 +++++----- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 8e9b71375c..55d41ae7d6 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -9780,7 +9780,16 @@ ShowAllGUCConfig(DestReceiver *dest) isnull[1] = true; } - values[2] = PointerGetDatum(cstring_to_text(conf->short_desc)); + if (conf->short_desc) + { + values[2] = PointerGetDatum(cstring_to_text(conf->short_desc)); + isnull[2] = false; + } + else + { + values[2] = PointerGetDatum(NULL); + isnull[2] = true; + } /* send it to dest */ do_tup_output(tstate, values, isnull); @@ -9792,7 +9801,8 @@ ShowAllGUCConfig(DestReceiver *dest) pfree(setting); pfree(DatumGetPointer(values[1])); } - pfree(DatumGetPointer(values[2])); + if (conf->short_desc) + pfree(DatumGetPointer(values[2])); } end_tup_output(tstate); @@ -10002,7 +10012,7 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow) values[3] = _(config_group_names[conf->group]); /* short_desc */ - values[4] = _(conf->short_desc); + values[4] = conf->short_desc != NULL ? _(conf->short_desc) : NULL; /* extra_desc */ values[5] = conf->long_desc != NULL ? _(conf->long_desc) : NULL; diff --git a/src/include/c.h b/src/include/c.h index 4f16e589b3..f253aa930b 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -144,6 +144,16 @@ #define pg_attribute_no_sanitize_alignment() #endif +/* + * pg_attribute_nonnull means the compiler should warn if the function is called + * with the listed arguments set to NULL. + */ +#if defined(__clang_major__) || defined(__GNUC__) +#define pg_attribute_nonnull(...) __attribute__((nonnull(__VA_ARGS__))) +#else +#define pg_attribute_nonnull(...) +#endif + /* * Append PG_USED_FOR_ASSERTS_ONLY to definitions of variables that are only * used in assert-enabled builds, to avoid compiler warnings about unused diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index efcbad7842..be691c5e9c 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -303,7 +303,7 @@ extern void DefineCustomBoolVariable(const char *name, int flags, GucBoolCheckHook check_hook, GucBoolAssignHook assign_hook, - GucShowHook show_hook); + GucShowHook show_hook) pg_attribute_nonnull(1, 4); extern void DefineCustomIntVariable(const char *name, const char *short_desc, @@ -316,7 +316,7 @@ extern void DefineCustomIntVariable(const char *name, int flags, GucIntCheckHook check_hook, GucIntAssignHook assign_hook, - GucShowHook show_hook); + GucShowHook show_hook) pg_attribute_nonnull(1, 4); extern void DefineCustomRealVariable(const char *name, const char *short_desc, @@ -329,7 +329,7 @@ extern void DefineCustomRealVariable(const char *name, int flags, GucRealCheckHook check_hook, GucRealAssignHook assign_hook, - GucShowHook show_hook); + GucShowHook show_hook) pg_attribute_nonnull(1, 4); extern void DefineCustomStringVariable(const char *name, const char *short_desc, @@ -340,7 +340,7 @@ extern void DefineCustomStringVariable(const char *name, int flags, GucStringCheckHook check_hook, GucStringAssignHook assign_hook, - GucShowHook show_hook); + GucShowHook show_hook) pg_attribute_nonnull(1, 4); extern void DefineCustomEnumVariable(const char *name, const char *short_desc, @@ -352,7 +352,7 @@ extern void DefineCustomEnumVariable(const char *name, int flags, GucEnumCheckHook check_hook, GucEnumAssignHook assign_hook, - GucShowHook show_hook); + GucShowHook show_hook) pg_attribute_nonnull(1, 4); extern void MarkGUCPrefixReserved(const char *className); -- 2.25.1