0001-libpq-exit-check-function-for-meson-and-Makefile.patch
text/x-patch
Filename: 0001-libpq-exit-check-function-for-meson-and-Makefile.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0001
Subject: libpq: Add exit() function check for Meson build and whitelist pthread_exit()
| File | + | − |
|---|---|---|
| meson.build | 1 | 0 |
| src/interfaces/libpq/Makefile | 4 | 3 |
| src/interfaces/libpq/meson.build | 32 | 38 |
From f711555fd2b69e74a33312f5ba8750b8fec97f1f Mon Sep 17 00:00:00 2001
From: BharatDBPG <bharatdbpg@gmail.com>
Date: Wed, 19 Nov 2025 12:17:43 +0530
Subject: [PATCH] libpq: Add exit() function check for Meson build and
whitelist pthread_exit()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Makefile-based build already performs a safety check to ensure that
libpq does not accidentally reference exit() or related termination
functions.
Meson, however, did not run this check. As a result, Meson builds could
miss accidental references to exit()-family functions which ideally
should never be called inside libpq.
This patch adds the missing scan to the Meson build by:
• Scanning the libpq .o files using nm and filtering through the same
whitelist logic as the Makefile.
• Adding pthread_exit() to the Meson whitelist, matching the behavior
of the existing Makefile check.
With this change, both Makefile and Meson builds apply the same
validation for unwanted exit() usage.
Signed-off-by: Vasuki[BharatDBPG] <bharatdbpg@gmail.com>
---
meson.build | 1 +
src/interfaces/libpq/Makefile | 7 ++--
src/interfaces/libpq/meson.build | 70 +++++++++++++++-----------------
3 files changed, 37 insertions(+), 41 deletions(-)
diff --git a/meson.build b/meson.build
index 24aeffe..e20bfe6 100644
--- a/meson.build
+++ b/meson.build
@@ -3812,6 +3812,7 @@ alias_target('bin', bin_targets + [libpq_st])
alias_target('pl', pl_targets)
alias_target('contrib', contrib_targets)
alias_target('testprep', testprep_targets)
+alias_target('run-check-libpq', [check_exit_target])
alias_target('world', all_built, docs)
alias_target('install-world', install_quiet, installdocs)
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 3bd0e4f..1ad3c60 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -134,9 +134,10 @@ $(stlib): $(OBJS_STATIC)
# build toolchains insert abort() calls, e.g. to implement assert().)
# If nm doesn't exist or doesn't work on shlibs, this test will do nothing,
# which is fine. The exclusion of __cxa_atexit is necessary on OpenBSD,
-# which seems to insert references to that even in pure C code. Excluding
-# __tsan_func_exit is necessary when using ThreadSanitizer data race detector
-# which use this function for instrumentation of function exit.
+# which seems to insert references to that even in pure C code. Excluding
+# __tsan_func_exit is necessary when using ThreadSanitizer, which emits this
+# symbol as part of its instrumentation of function exits. Excluding
+# pthread_exit allows legitimate thread shutdown paths used on some builds.
# Skip the test when profiling, as gcc may insert exit() calls for that.
# Also skip the test on platforms where libpq infrastructure may be provided
# by statically-linked libraries, as we can't expect them to honor this
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index 4b1e8a2..4822814 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -1,5 +1,4 @@
# Copyright (c) 2022-2025, PostgreSQL Global Development Group
-
libpq_sources = files(
'fe-auth-oauth.c',
'fe-auth-scram.c',
@@ -85,6 +84,38 @@ libpq = declare_dependency(
include_directories: [include_directories('.')]
)
+# Sanity check to ensure libpq does not contain any unintended references
+# to exit() in its object files. Client libraries must not terminate the
+# calling process, so we scan all libpq .o files with 'nm' and fail the
+# build if a direct exit() reference is found. Certain harmless symbols
+# (__cxa_atexit, __tsan_func_exit, pthread_exit) are whitelisted.
+# Skip on cross-builds, sanitizer coverage, and Windows
+
+if not meson.is_cross_build() and not get_option('b_coverage') and host_system != 'windows'
+ check_exit_target = custom_target(
+ 'check-libpq-no-exit',
+ output: 'libpq-nm-stamp',
+ depends: [libpq_st, libpq_so],
+ build_by_default: true,
+ command: [
+ 'bash','-eu', '-c',
+ '''
+ echo "Checking that libpq object files do not reference exit()..."
+ obj_files=$(find src/interfaces/libpq -type f -name "*.o")
+ for f in $obj_files; do
+ if nm -u "$f" 2>/dev/null \
+ | grep -v -E '__cxa_atexit|__tsan_func_exit|pthread_exit' \
+ | grep exit; then
+ echo "ERROR: exit()-related reference found in: $f"
+ exit 1
+ fi
+ done
+ touch @OUTPUT@
+ '''.format(meson.current_build_dir())
+ ],
+ )
+
+endif
private_deps = [
frontend_stlib_code,
@@ -147,41 +178,4 @@ tests += {
},
}
-# Verify that libpq does not reference functions that may invoke exit().
-#
-# This check parallels the Makefile logic used in the autoconf build system.
-#
-# The following symbols are considered safe and therefore ignored:
-# - __cxa_atexit : used for C++ static destructors
-# - __tsan_func_exit : thread sanitizer instrumentation
-# - pthread_exit : used by thread runtimes, harmless here
-#
-# The test runs only for native builds (not cross-builds) and when code
-# coverage is disable
-
-if not meson.is_cross_build() and not get_option('b_coverage') and host_system != 'sunos'
- check_exit_target = custom_target(
- 'check-libpq-no-exit',
- output: 'libpq-refs-stamp',
- depends: libpq_so,
- build_by_default: true,
- command: [
- 'bash', '-c',
- '''
- echo "Running exit() reference check for libpq..."
- if nm -A -u @0@ 2>/dev/null | \
- grep -v -e __cxa_atexit -e __tsan_func_exit -e pthread_exit | \
- grep exit; then
- echo "ERROR: libpq must not be calling any function which invokes exit()"
- exit 1
- else
- echo "SUCCESS: No exit() references found in libpq"
- fi
- '''.format(libpq_so.full_path())
- ],
- build_always_stale: true,
- capture: false
- )
-endif
-
subdir('po', if_found: libintl)
--
2.43.0