develooper Front page | perl.perl5.porters | Postings from October 2005

[perl #37376] Perl's assumptions about environ are invalid on Solaris 10

Alan Burlison
October 7, 2005 14:40
[perl #37376] Perl's assumptions about environ are invalid on Solaris 10
Message ID:
# New Ticket Created by  Alan Burlison 
# Please include the string:  [perl #37376]
# in the subject line of all future correspondence about this issue. 
# <URL: >

This is a bug report for perl from,
generated with the help of perlbug 1.35 running under perl v5.8.7.

[Please enter your report here]

I've been trying to get DBD::Oracle to build with Oracle's new "Instant Client"
and have been getting bizzare "out of memory" errors in perl_destruct.  To cut
a long story short, this is caused by perl's handling of environ.

During Solaris 10 development the algorithm by which the environ array
of a process is managed changed so that the buffer allocated to hold the
environ array is filled from high to low addresses rather than the old low to
high mechanism.  This was done for MT performance reasons, so that lock-free
environment handling could be used.  The new code can be seen at

Perl_my_setenv directly manipulates the environ pointer and addition it makes
assumptions as to what environ actually points to - namely that environ points
to the start of a malloc'd buffer, so when perl wishes to grow environ it does
so by realloc'ing it.  Unfortunately, on S10 environ does not necessarily point
to the start of the buffer (in most cases it won't) so perl's attempt to
realloc the buffer results in heap corruption with subsequent hard-to-diagnose
failures happening some time later.

The specific scenario that triggered this is that the Oracle "Instant Client"
libraries modify the environment with libc's putenv, causing the environment to
be grown, then DBD::Oracle module subsequently modifies %ENV which in
turn results in perl trying to realloc environ (which now points into the
middle of a malloc'd block), and things rapidly go downhill from that point.

According to the INSTALL file, the reason that perl instituted it's own
environment handling was to fix memory leaks related to envirionment handling
on some platforms.  The getenv/putenv API is leaky by virtue of it's less than
optimal design, so I'm not sure why this was considered necessary.  The problem
with the perl environ handling is that it makes assumptions about what system
lbraries and external code will and won't do with the environ pointer.  POSIX.1
2001 conformance forbids applications from modifying environ directly when they
use APIs such as getenv() and setenv(), and perl can't ever be sure that this
won't be the case.  The fact that perl has the PERL_USE_SAFE_PUTENV macro to
disable the environ fiddling at compile time *and* the PL_use_safe_putenv
variable to enable applications that embed perl to disable it at run-time is a
clear indication that perl's behaviour in this area is badly damaged.  Indeed
the Solaris setenv(3C) manpage clearly states:

     If the application modifies environ or the pointers to which
     it  points,  the  behavior  of  setenv()  is  undefined. The
     setenv() function updates the  list  of  pointers  to  which
     environ points.

I feel that all the code that directly manipulates environ should be removed as
it is dangerous, causes more problems than it solves and leads to random and
therefore difficult to debug heap corruption.

[Please do not change anything below this line]
Site configuration information for perl v5.8.7:

Summary of my perl5 (revision 5 version 8 subversion 7) configuration:
    osname=solaris, osvers=2.11, archname=i86pc-solaris-64int
    uname='sunos localhost 5.11 i86pc i386 i86pc'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=define use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
    ccversion='Sun WorkShop', gccversion='', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =''
    libpth=/lib /usr/lib /usr/ccs/lib
    libs=-lsocket -lnsl -ldl -lm -lc
    perllibs=-lsocket -lnsl -ldl -lm -lc
    libc=/lib/, so=so, useshrplib=true,
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-R /scafoldd/perl5/5.8.7/lib/i86pc-solaris-64int/CORE'
    cccdlflags='-KPIC', lddlflags='-G'

Locally applied patches:

@INC for perl v5.8.7:

Environment for perl v5.8.7:
    LANGUAGE (unset)
    LOGDIR (unset)
    PERL_BADLANG (unset)
    SHELL=/bin/ksh Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About