libpq causes segfault when share library unloaded

From: Jim Studt <jim(at)federated(dot)com>
To: pgsql-bugs(at)postgreSQL(dot)org
Subject: libpq causes segfault when share library unloaded
Date: 1999-11-04 17:02:22
Message-ID: 199911041702.LAA22180@core.federated.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

============================================================================
POSTGRESQL BUG REPORT TEMPLATE
============================================================================

Your name : Jim Studt
Your email address : jim(at)federated(dot)com

System Configuration
---------------------
Architecture (example: Intel Pentium) : Intel Pentium

Operating System (example: Linux 2.0.26 ELF) : Linux 2.2.13

PostgreSQL version (example: PostgreSQL-6.5.2): PostgreSQL-6.5.2

Compiler used (example: gcc 2.8.0) : gcc 2.95.2 19991024

Please enter a FULL description of your problem:
------------------------------------------------
libpq will define an environment variable for PGCLIENTENCODING if
none is specified. If libpq is a shared library that is dynamically
loaded, and it is subsequently unloaded then it leaves an entry in
the environ array pointing into unmapped memory which will cause
a segfault the next time the environment array is traversed.

Please describe a way to repeat the problem. Please try to provide a
concise reproducible example, if at all possible:
----------------------------------------------------------------------

/*
** program to demonstrate segfault from a putenv in a
** dynamicall loaded library.
** Build with something like: make breaklibpq LDLIBS=-ldl
** DO NOT link to libpq.
*/

#include <postgresql/libpq-fe.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

main()
{
typedef PGconn *(*ConnFunc)();
typedef int(*PQstatusType)();

void *dl;
ConnFunc func;
PGconn *conn;
PQstatusType statfunc;

printf("initially getenv(PGCLIENTENCODING) is %08x\n",
getenv("PGCLIENTENCODING"));

/* load the libpq dynamically */
dl = dlopen("libpq.so",RTLD_NOW);
if ( !dl) {
fprintf(stderr,"Failed to open libpq: %s\n", dlerror());
exit(1);
}

/* find PQconnectdb */
func = (ConnFunc)dlsym(dl,"PQconnectdb");
if ( !func) {
fprintf(stderr,"Failed to find PQconnectdb in libpq: %s\n",
dlerror());
exit(1);
}

/* find PQstatus */
statfunc = (PQstatusType)dlsym(dl,"PQstatus");
if ( !statfunc) {
fprintf(stderr,"Failed to find PQstatus in libpq: %s\n",
dlerror());
exit(1);
}

/* call PQconnectdb */
conn = (*func)("dbname=template1");
if ( !conn || (*statfunc)(conn) == CONNECTION_BAD) {
fprintf(stderr,"Failed to connect to template1\n");
exit(1);
}

printf("after connect getenv(PGCLIENTENCODING) is %08x\n",
getenv("PGCLIENTENCODING"));

/* close the library, as reference this will unmap it */
dlclose(dl);

/* we should segfault in the upcoming getenv() call */
printf("after close getenv(PGCLIENTENCODING) is %08x\n",
getenv("PGCLIENTENCODING"));
}

If you know how this problem might be fixed, list the solution below:
---------------------------------------------------------------------
A library should either find a way to clean up its putenv changes
when unloaded or not make them. I would lean toward keeping the
client encoding in a global variable for use within libpq (its only
used once over in PQmblen(). If it needs to be exposed to the client
then an API call should be added.

It may be possible to use special linker sections to arrange for
cleanup code when a library is unloaded, like C++ static destructors
use on some systems. This would probably be a portability nightmare.

--
Jim Studt, President
The Federated Software Group, Inc.

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 1999-11-05 01:16:38 Re: [BUGS] libpq causes segfault when share library unloaded
Previous Message Jim Studt 1999-11-04 16:17:21 libpq can cause segfaults if unloaded