Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcec0c21

Browse files
committed
Diagnose incompatible OpenLDAP versions during build and test.
With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, PostgreSQLbackends can crash at exit. Raise a warning during "configure" based onthe compile-time OpenLDAP version number, and test the crash scenario inthe dblink test suite. Back-patch to 9.0 (all supported versions).
1 parentf54d97c commitcec0c21

File tree

11 files changed

+244
-1
lines changed

11 files changed

+244
-1
lines changed

‎configure

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13663,6 +13663,17 @@ fi
1366313663

1366413664
fi
1366513665

13666+
# PGAC_LDAP_SAFE
13667+
# --------------
13668+
# PostgreSQL sometimes loads libldap_r and plain libldap into the same
13669+
# process. Check for OpenLDAP versions known not to tolerate doing so; assume
13670+
# non-OpenLDAP implementations are safe. The dblink test suite exercises the
13671+
# hazardous interaction directly.
13672+
13673+
13674+
13675+
13676+
1366613677
if test "$with_ldap" = yes ; then
1366713678
if test "$PORTNAME" != "win32"; then
1366813679

@@ -13820,6 +13831,72 @@ fi
1382013831

1382113832
done
1382213833

13834+
{ $as_echo "$as_me:$LINENO: checking for compatible LDAP implementation" >&5
13835+
$as_echo_n "checking for compatible LDAP implementation... " >&6; }
13836+
if test "${pgac_cv_ldap_safe+set}" = set; then
13837+
$as_echo_n "(cached) " >&6
13838+
else
13839+
cat >conftest.$ac_ext <<_ACEOF
13840+
/* confdefs.h. */
13841+
_ACEOF
13842+
cat confdefs.h >>conftest.$ac_ext
13843+
cat >>conftest.$ac_ext <<_ACEOF
13844+
/* end confdefs.h. */
13845+
#include <ldap.h>
13846+
#if !defined(LDAP_VENDOR_VERSION) || \
13847+
(defined(LDAP_API_FEATURE_X_OPENLDAP) && \
13848+
LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
13849+
choke me
13850+
#endif
13851+
int
13852+
main ()
13853+
{
13854+
13855+
;
13856+
return 0;
13857+
}
13858+
_ACEOF
13859+
rm -f conftest.$ac_objext
13860+
if { (ac_try="$ac_compile"
13861+
case "(($ac_try" in
13862+
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
13863+
*) ac_try_echo=$ac_try;;
13864+
esac
13865+
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
13866+
$as_echo "$ac_try_echo") >&5
13867+
(eval "$ac_compile") 2>conftest.er1
13868+
ac_status=$?
13869+
grep -v '^ *+' conftest.er1 >conftest.err
13870+
rm -f conftest.er1
13871+
cat conftest.err >&5
13872+
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
13873+
(exit $ac_status); } && {
13874+
test -z "$ac_c_werror_flag" ||
13875+
test ! -s conftest.err
13876+
} && test -s conftest.$ac_objext; then
13877+
pgac_cv_ldap_safe=yes
13878+
else
13879+
$as_echo "$as_me: failed program was:" >&5
13880+
sed 's/^/| /' conftest.$ac_ext >&5
13881+
13882+
pgac_cv_ldap_safe=no
13883+
fi
13884+
13885+
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
13886+
fi
13887+
{ $as_echo "$as_me:$LINENO: result: $pgac_cv_ldap_safe" >&5
13888+
$as_echo "$pgac_cv_ldap_safe" >&6; }
13889+
13890+
if test "$pgac_cv_ldap_safe" != yes; then
13891+
{ $as_echo "$as_me:$LINENO: WARNING:
13892+
*** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
13893+
*** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
13894+
*** also uses LDAP will crash on exit." >&5
13895+
$as_echo "$as_me: WARNING:
13896+
*** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
13897+
*** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
13898+
*** also uses LDAP will crash on exit." >&2;}
13899+
fi
1382313900
else
1382413901

1382513902
for ac_header in winldap.h

‎configure.in

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

1070+
# PGAC_LDAP_SAFE
1071+
# --------------
1072+
# PostgreSQL sometimes loads libldap_r and plain libldap into the same
1073+
# process. Check for OpenLDAP versions known not to tolerate doing so; assume
1074+
# non-OpenLDAP implementations are safe. The dblink test suite exercises the
1075+
# hazardous interaction directly.
1076+
1077+
AC_DEFUN([PGAC_LDAP_SAFE],
1078+
[AC_CACHE_CHECK([for compatible LDAP implementation], [pgac_cv_ldap_safe],
1079+
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
1080+
[#include <ldap.h>
1081+
#if !defined(LDAP_VENDOR_VERSION) || \
1082+
(defined(LDAP_API_FEATURE_X_OPENLDAP) && \
1083+
LDAP_VENDOR_VERSION >= 20424 && LDAP_VENDOR_VERSION <= 20431)
1084+
choke me
1085+
#endif], [])],
1086+
[pgac_cv_ldap_safe=yes],
1087+
[pgac_cv_ldap_safe=no])])
1088+
1089+
if test "$pgac_cv_ldap_safe" != yes; then
1090+
AC_MSG_WARN([
1091+
*** With OpenLDAP versions 2.4.24 through 2.4.31, inclusive, each backend
1092+
*** process that loads libpq (via WAL receiver, dblink, or postgres_fdw) and
1093+
*** also uses LDAP will crash on exit.])
1094+
fi])
1095+
1096+
1097+
10701098
if test "$with_ldap" = yes ; then
10711099
if test "$PORTNAME" != "win32"; then
10721100
AC_CHECK_HEADERS(ldap.h, [],
10731101
[AC_MSG_ERROR([header file <ldap.h> is required for LDAP])])
1102+
PGAC_LDAP_SAFE
10741103
else
10751104
AC_CHECK_HEADERS(winldap.h, [],
10761105
[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.0.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
overrideUSE_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
@@ -105,6 +105,33 @@ SELECT *
105105
FROM dblink('SELECT * FROM foo') AS t(a int, b text, c text[])
106106
WHERE t.a > 7;
107107
ERROR: connection not available
108+
-- The first-level connection's backend will crash on exit given OpenLDAP
109+
-- [2.4.24, 2.4.31]. We won't see evidence of any crash until the victim
110+
-- process terminates and the postmaster responds. If process termination
111+
-- entails writing a core dump, that can take awhile. Wait for the process to
112+
-- vanish. At that point, the postmaster has called waitpid() on the crashed
113+
-- process, and it will accept no new connections until it has reinitialized
114+
-- the cluster. (We can't exploit pg_stat_activity, because the crash happens
115+
-- after the backend updates shared memory to reflect its impending exit.)
116+
DO $pl$
117+
DECLARE
118+
detail text;
119+
BEGIN
120+
PERFORM wait_pid(crash_pid)
121+
FROM dblink('dbname=contrib_regression', $$
122+
SELECT pg_backend_pid() FROM dblink(
123+
'service=test_ldap dbname=contrib_regression',
124+
-- This string concatenation is a hack to shoehorn a
125+
-- set_pgservicefile call into the SQL statement.
126+
'SELECT 1' || set_pgservicefile('pg_service.conf')
127+
) t(c int)
128+
$$) AS t(crash_pid int);
129+
EXCEPTION WHEN OTHERS THEN
130+
GET STACKED DIAGNOSTICS detail = PG_EXCEPTION_DETAIL;
131+
-- Expected error in a non-LDAP build.
132+
IF NOT detail LIKE 'syntax error in service file%' THEN RAISE; END IF;
133+
END
134+
$pl$;
108135
-- create a persistent connection
109136
SELECT dblink_connect('dbname=contrib_regression');
110137
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(aint, btext, ctext[])
6666
WHEREt.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+
detailtext;
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(cint)
88+
$$)AS t(crash_pidint);
89+
EXCEPTION WHEN OTHERS THEN
90+
GET STACKED DIAGNOSTICS detail= PG_EXCEPTION_DETAIL;
91+
-- Expected error in a non-LDAP build.
92+
IF NOT detailLIKE'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

‎src/test/regress/regress.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include<float.h>
88
#include<math.h>
9+
#include<signal.h>
910

1011
#include"access/transam.h"
1112
#include"access/xact.h"
@@ -14,8 +15,10 @@
1415
#include"commands/trigger.h"
1516
#include"executor/executor.h"
1617
#include"executor/spi.h"
18+
#include"miscadmin.h"
1719
#include"utils/builtins.h"
1820
#include"utils/geo_decls.h"
21+
#include"utils/memutils.h"
1922
#include"utils/rel.h"
2023

2124

@@ -35,6 +38,8 @@ extern char *reverse_name(char *string);
3538
externintoldstyle_length(intn,text*t);
3639
externDatumint44in(PG_FUNCTION_ARGS);
3740
externDatumint44out(PG_FUNCTION_ARGS);
41+
externDatumregress_putenv(PG_FUNCTION_ARGS);
42+
externDatumwait_pid(PG_FUNCTION_ARGS);
3843

3944
#ifdefPG_MODULE_MAGIC
4045
PG_MODULE_MAGIC;
@@ -737,3 +742,44 @@ int44out(PG_FUNCTION_ARGS)
737742
*--walk='\0';
738743
PG_RETURN_CSTRING(result);
739744
}
745+
746+
PG_FUNCTION_INFO_V1(regress_putenv);
747+
748+
Datum
749+
regress_putenv(PG_FUNCTION_ARGS)
750+
{
751+
MemoryContextoldcontext;
752+
char*envbuf;
753+
754+
if (!superuser())
755+
elog(ERROR,"must be superuser to change environment variables");
756+
757+
oldcontext=MemoryContextSwitchTo(TopMemoryContext);
758+
envbuf=text_to_cstring((text*)PG_GETARG_POINTER(0));
759+
MemoryContextSwitchTo(oldcontext);
760+
761+
if (putenv(envbuf)!=0)
762+
elog(ERROR,"could not set environment variable: %m");
763+
764+
PG_RETURN_VOID();
765+
}
766+
767+
/* Sleep until no process has a given PID. */
768+
PG_FUNCTION_INFO_V1(wait_pid);
769+
770+
Datum
771+
wait_pid(PG_FUNCTION_ARGS)
772+
{
773+
intpid=PG_GETARG_INT32(0);
774+
775+
if (!superuser())
776+
elog(ERROR,"must be superuser to check PID liveness");
777+
778+
while (kill(pid,0)==0)
779+
pg_usleep(50000);
780+
781+
if (errno!=ESRCH)
782+
elog(ERROR,"could not check PID %d liveness: %m",pid);
783+
784+
PG_RETURN_VOID();
785+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp