Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fd18965

Browse files
committed
Diagnose incompatible OpenLDAP versions during build and test.
With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, PostgreSQL backends can crash at exit. Raise a warning during "configure" based on the compile-time OpenLDAP version number, and test the crash scenario in the dblink test suite. Back-patch to 9.0 (all supported versions).
1 parent 87c4232 commit fd18965

File tree

11 files changed

+216
-1
lines changed

11 files changed

+216
-1
lines changed

configure

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9477,6 +9477,17 @@ fi
94779477

94789478
fi
94799479

9480+
# PGAC_LDAP_SAFE
9481+
# --------------
9482+
# PostgreSQL sometimes loads libldap_r and plain libldap into the same
9483+
# process. Check for OpenLDAP versions known not to tolerate doing so; assume
9484+
# non-OpenLDAP implementations are safe. The dblink test suite exercises the
9485+
# hazardous interaction directly.
9486+
9487+
9488+
9489+
9490+
94809491
if test "$with_ldap" = yes ; then
94819492
if test "$PORTNAME" != "win32"; then
94829493
for ac_header in ldap.h
@@ -9493,6 +9504,47 @@ fi
94939504

94949505
done
94959506

9507+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compatible LDAP implementation" >&5
9508+
$as_echo_n "checking for compatible LDAP implementation... " >&6; }
9509+
if ${pgac_cv_ldap_safe+:} false; then :
9510+
$as_echo_n "(cached) " >&6
9511+
else
9512+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
9513+
/* end confdefs.h. */
9514+
#include <ldap.h>
9515+
#if !defined(LDAP_VENDOR_VERSION) || \
9516+
(defined(LDAP_API_FEATURE_X_OPENLDAP) && \
9517+
LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
9518+
choke me
9519+
#endif
9520+
int
9521+
main ()
9522+
{
9523+
9524+
;
9525+
return 0;
9526+
}
9527+
_ACEOF
9528+
if ac_fn_c_try_compile "$LINENO"; then :
9529+
pgac_cv_ldap_safe=yes
9530+
else
9531+
pgac_cv_ldap_safe=no
9532+
fi
9533+
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
9534+
fi
9535+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_ldap_safe" >&5
9536+
$as_echo "$pgac_cv_ldap_safe" >&6; }
9537+
9538+
if test "$pgac_cv_ldap_safe" != yes; then
9539+
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
9540+
*** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
9541+
*** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
9542+
*** also uses LDAP will crash on exit." >&5
9543+
$as_echo "$as_me: WARNING:
9544+
*** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
9545+
*** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
9546+
*** also uses LDAP will crash on exit." >&2;}
9547+
fi
94969548
else
94979549
for ac_header in winldap.h
94989550
do :

configure.in

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,10 +1098,39 @@ if test "$with_libxslt" = yes ; then
10981098
AC_CHECK_HEADER(libxslt/xslt.h, [], [AC_MSG_ERROR([header file <libxslt/xslt.h> is required for XSLT support])])
10991099
fi
11001100

1101+
# PGAC_LDAP_SAFE
1102+
# --------------
1103+
# PostgreSQL sometimes loads libldap_r and plain libldap into the same
1104+
# process. Check for OpenLDAP versions known not to tolerate doing so; assume
1105+
# non-OpenLDAP implementations are safe. The dblink test suite exercises the
1106+
# hazardous interaction directly.
1107+
1108+
AC_DEFUN([PGAC_LDAP_SAFE],
1109+
[AC_CACHE_CHECK([for compatible LDAP implementation], [pgac_cv_ldap_safe],
1110+
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
1111+
[#include <ldap.h>
1112+
#if !defined(LDAP_VENDOR_VERSION) || \
1113+
(defined(LDAP_API_FEATURE_X_OPENLDAP) && \
1114+
LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
1115+
choke me
1116+
#endif], [])],
1117+
[pgac_cv_ldap_safe=yes],
1118+
[pgac_cv_ldap_safe=no])])
1119+
1120+
if test "$pgac_cv_ldap_safe" != yes; then
1121+
AC_MSG_WARN([
1122+
*** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
1123+
*** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
1124+
*** also uses LDAP will crash on exit.])
1125+
fi])
1126+
1127+
1128+
11011129
if test "$with_ldap" = yes ; then
11021130
if test "$PORTNAME" != "win32"; then
11031131
AC_CHECK_HEADERS(ldap.h, [],
11041132
[AC_MSG_ERROR([header file <ldap.h> is required for LDAP])])
1133+
PGAC_LDAP_SAFE
11051134
else
11061135
AC_CHECK_HEADERS(winldap.h, [],
11071136
[AC_MSG_ERROR([header file <winldap.h> is required for LDAP])],

contrib/dblink/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ SHLIB_PREREQS = submake-libpq
99
EXTENSION = dblink
1010
DATA = dblink--1.1.sql dblink--1.0--1.1.sql dblink--unpackaged--1.0.sql
1111

12-
REGRESS = dblink
12+
REGRESS = paths dblink
13+
REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress
14+
EXTRA_CLEAN = sql/paths.sql expected/paths.out
1315

1416
# the db name is hard-coded in the tests
1517
override USE_MODULE_DB =

contrib/dblink/expected/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/paths.out

contrib/dblink/expected/dblink.out

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,33 @@ SELECT *
103103
FROM dblink('SELECT * FROM foo') AS t(a int, b text, c text[])
104104
WHERE t.a > 7;
105105
ERROR: connection not available
106+
-- The first-level connection's backend will crash on exit given OpenLDAP
107+
-- [2.4.24, 2.4.31]. We won't see evidence of any crash until the victim
108+
-- process terminates and the postmaster responds. If process termination
109+
-- entails writing a core dump, that can take awhile. Wait for the process to
110+
-- vanish. At that point, the postmaster has called waitpid() on the crashed
111+
-- process, and it will accept no new connections until it has reinitialized
112+
-- the cluster. (We can't exploit pg_stat_activity, because the crash happens
113+
-- after the backend updates shared memory to reflect its impending exit.)
114+
DO $pl$
115+
DECLARE
116+
detail text;
117+
BEGIN
118+
PERFORM wait_pid(crash_pid)
119+
FROM dblink('dbname=contrib_regression', $$
120+
SELECT pg_backend_pid() FROM dblink(
121+
'service=test_ldap dbname=contrib_regression',
122+
-- This string concatenation is a hack to shoehorn a
123+
-- set_pgservicefile call into the SQL statement.
124+
'SELECT 1' || set_pgservicefile('pg_service.conf')
125+
) t(c int)
126+
$$) AS t(crash_pid int);
127+
EXCEPTION WHEN OTHERS THEN
128+
GET STACKED DIAGNOSTICS detail = PG_EXCEPTION_DETAIL;
129+
-- Expected error in a non-LDAP build.
130+
IF NOT detail LIKE 'syntax error in service file%' THEN RAISE; END IF;
131+
END
132+
$pl$;
106133
-- create a persistent connection
107134
SELECT dblink_connect('dbname=contrib_regression');
108135
dblink_connect

contrib/dblink/input/paths.source

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- Initialization that requires path substitution.
2+
3+
CREATE FUNCTION putenv(text)
4+
RETURNS void
5+
AS '@libdir@/regress@DLSUFFIX@', 'regress_putenv'
6+
LANGUAGE C STRICT;
7+
8+
CREATE FUNCTION wait_pid(int)
9+
RETURNS void
10+
AS '@libdir@/regress@DLSUFFIX@'
11+
LANGUAGE C STRICT;
12+
13+
CREATE FUNCTION set_pgservicefile(text) RETURNS void LANGUAGE SQL
14+
AS $$SELECT putenv('PGSERVICEFILE=@abs_srcdir@/' || $1)$$;

contrib/dblink/output/paths.source

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- Initialization that requires path substitution.
2+
CREATE FUNCTION putenv(text)
3+
RETURNS void
4+
AS '@libdir@/regress@DLSUFFIX@', 'regress_putenv'
5+
LANGUAGE C STRICT;
6+
CREATE FUNCTION wait_pid(int)
7+
RETURNS void
8+
AS '@libdir@/regress@DLSUFFIX@'
9+
LANGUAGE C STRICT;
10+
CREATE FUNCTION set_pgservicefile(text) RETURNS void LANGUAGE SQL
11+
AS $$SELECT putenv('PGSERVICEFILE=@abs_srcdir@/' || $1)$$;

contrib/dblink/pg_service.conf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# pg_service.conf for minimally exercising libpq use of LDAP.
2+
3+
# Having failed to reach an LDAP server, libpq essentially ignores the
4+
# "service=test_ldap" in its connection string. Contact the "discard"
5+
# service; the test works whether or not it answers.
6+
[test_ldap]
7+
ldap://127.0.0.1:9/base?attribute?one?filter

contrib/dblink/sql/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/paths.sql

contrib/dblink/sql/dblink.sql

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,34 @@ SELECT *
6565
FROM dblink('SELECT * FROM foo') AS t(a int, b text, c text[])
6666
WHERE t.a > 7;
6767

68+
-- The first-level connection's backend will crash on exit given OpenLDAP
69+
-- [2.4.24, 2.4.31]. We won't see evidence of any crash until the victim
70+
-- process terminates and the postmaster responds. If process termination
71+
-- entails writing a core dump, that can take awhile. Wait for the process to
72+
-- vanish. At that point, the postmaster has called waitpid() on the crashed
73+
-- process, and it will accept no new connections until it has reinitialized
74+
-- the cluster. (We can't exploit pg_stat_activity, because the crash happens
75+
-- after the backend updates shared memory to reflect its impending exit.)
76+
DO $pl$
77+
DECLARE
78+
detail text;
79+
BEGIN
80+
PERFORM wait_pid(crash_pid)
81+
FROM dblink('dbname=contrib_regression', $$
82+
SELECT pg_backend_pid() FROM dblink(
83+
'service=test_ldap dbname=contrib_regression',
84+
-- This string concatenation is a hack to shoehorn a
85+
-- set_pgservicefile call into the SQL statement.
86+
'SELECT 1' || set_pgservicefile('pg_service.conf')
87+
) t(c int)
88+
$$) AS t(crash_pid int);
89+
EXCEPTION WHEN OTHERS THEN
90+
GET STACKED DIAGNOSTICS detail = PG_EXCEPTION_DETAIL;
91+
-- Expected error in a non-LDAP build.
92+
IF NOT detail LIKE 'syntax error in service file%' THEN RAISE; END IF;
93+
END
94+
$pl$;
95+
6896
-- create a persistent connection
6997
SELECT dblink_connect('dbname=contrib_regression');
7098

0 commit comments

Comments
 (0)