From f0679266bda765f4e1e15bfee97d2817d3bd78ea Mon Sep 17 00:00:00 2001 From: BharatDBPG Date: Wed, 19 Nov 2025 17:43:53 +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. --- meson.build | 1 + src/interfaces/libpq/Makefile | 5 +++-- src/interfaces/libpq/meson.build | 30 ++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index c1e17aa3040..47588ead9fb 100644 --- a/meson.build +++ b/meson.build @@ -3820,6 +3820,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 da6650066d4..7b20d84d51d 100644 --- a/src/interfaces/libpq/Makefile +++ b/src/interfaces/libpq/Makefile @@ -137,14 +137,15 @@ $(stlib): $(OBJS_STATIC) # 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. -# Skip the test when profiling, as gcc may insert exit() calls for that. +#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 # coding rule. libpq-refs-stamp: $(shlib) ifneq ($(enable_coverage), yes) ifeq (,$(filter solaris,$(PORTNAME))) - @if nm -A -u $< 2>/dev/null | grep -v -e __cxa_atexit -e __tsan_func_exit | grep exit; then \ + @if nm -A -u $< 2>/dev/null | grep -v -e __cxa_atexit -e __tsan_func_exit -e pthread_exit | grep exit; then \ echo 'libpq must not be calling any function which invokes exit'; exit 1; \ fi endif diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build index a74e885b169..30324731e9c 100644 --- a/src/interfaces/libpq/meson.build +++ b/src/interfaces/libpq/meson.build @@ -85,6 +85,36 @@ 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, libpq_deps, -- 2.43.0