Skip site navigation (1) Skip section navigation (2)

libpq can cause segfaults if unloaded

From: Jim Studt <jim(at)federated(dot)com>
To: pgsql-bugs(at)postgresql(dot)org
Subject: libpq can cause segfaults if unloaded
Date: 1999-11-04 16:17:21
Message-ID: (view raw, whole thread or download thread mbox)
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>

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

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

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

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

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

    /* find PQstatus */
    statfunc = (PQstatusType)dlsym(dl,"PQstatus");
    if ( !statfunc) {
	fprintf(stderr,"Failed to find PQstatus in libpq: %s\n", 
    /* call PQconnectdb */
    conn = (*func)("dbname=template1");
    if ( !conn || (*statfunc)(conn) == CONNECTION_BAD) {
	fprintf(stderr,"Failed to connect to template1\n");

    printf("after connect getenv(PGCLIENTENCODING) is %08x\n", 
    /* close the library, as reference this will unmap it */

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

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.

pgsql-bugs by date

Next:From: Jim StudtDate: 1999-11-04 17:02:22
Subject: libpq causes segfault when share library unloaded
Previous:From: Enrico ScholzDate: 1999-11-03 14:21:28
Subject: Missing default-operator-class at a "TIMESTAMP UNIQUE" column

Privacy Policy | About PostgreSQL
Copyright © 1996-2017 The PostgreSQL Global Development Group