After some reading I don't think we can blindly
Jarkko Hietaniemi [Wed, 20 Jun 2001 04:54:53 +0000 (04:54 +0000)]
use systems' realpath().  Too many security problems,
too many buggy implementations.

TODO: the realpath() emulation code in util.c doesn't
seem fully operational?  (readlink(), for example?)

p4raw-id: //depot/perl@10744

20 files changed:
Configure
Makefile.micro
Porting/Glossary
Porting/config.sh
Porting/config_H
config_h.SH
embed.pl
perlapi.c
pod/perldiag.pod
pod/perltoc.pod
uconfig.h
uconfig.sh
util.c
vos/config.alpha.def
vos/config.alpha.h
vos/config.ga.def
vos/config.ga.h
win32/config_H.bc
win32/config_H.gc
win32/config_H.vc

index b6ed6d9..2f76d15 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -20,7 +20,7 @@
 
 # $Id: Head.U,v 3.0.1.9 1997/02/28 15:02:09 ram Exp $
 #
-# Generated on Wed Jun 20 02:24:20 EET DST 2001 [metaconfig 3.0 PL70]
+# Generated on Wed Jun 20 08:47:08 EET DST 2001 [metaconfig 3.0 PL70]
 # (with additional metaconfig patches by perlbug@perl.org)
 
 cat >c1$$ <<EOF
@@ -485,7 +485,6 @@ d_seekdir=''
 d_telldir=''
 d_readlink=''
 d_readv=''
-d_realpath=''
 d_recvmsg=''
 d_rename=''
 d_rmdir=''
@@ -11407,10 +11406,6 @@ eval $inlibc
 set readv d_readv
 eval $inlibc
 
-: see if realpath exists
-set realpath d_realpath
-eval $inlibc
-
 : see if recvmsg exists
 set recvmsg d_recvmsg
 eval $inlibc
@@ -16717,7 +16712,6 @@ d_quad='$d_quad'
 d_readdir='$d_readdir'
 d_readlink='$d_readlink'
 d_readv='$d_readv'
-d_realpath='$d_realpath'
 d_recvmsg='$d_recvmsg'
 d_rename='$d_rename'
 d_rewinddir='$d_rewinddir'
index 4ed2a1c..78113aa 100644 (file)
@@ -16,7 +16,7 @@ O = uav$(_O) udeb$(_O) udoio$(_O) udoop$(_O) udump$(_O) \
        uregcomp$(_O) uregexec$(_O) urun$(_O) \
        uscope$(_O) usv$(_O) utaint$(_O) utoke$(_O) \
        unumeric$(_O) ulocale$(_O) \
-       uuniversal$(_O) uutf8$(_O) uutil$(_O) uperlapi$(_O) \
+       uuniversal$(_O) uutf8$(_O) uutil$(_O) uperlapi$(_O)
 
 microperl:     $(O)
        $(LD) -o $@ $(O) $(LIBS)
index 26e6e4c..fa87e63 100644 (file)
@@ -1258,10 +1258,6 @@ d_readv (d_readv.U):
        This variable conditionally defines the HAS_READV symbol, which
        indicates to the C program that the readv() routine is available.
 
-d_realpath (d_realpath.U):
-       This variable conditionally defines the HAS_REALPATH symbol, which
-       indicates to the C program that the realpath() routine is available.
-
 d_recvmsg (d_recvmsg.U):
        This variable conditionally defines the HAS_RECVMSG symbol, which
        indicates to the C program that the recvmsg() routine is available.
index b804e95..5dc8a7e 100644 (file)
@@ -8,7 +8,7 @@
 
 # Package name      : perl5
 # Source directory  : .
-# Configuration time: Fri Jun 15 02:15:37 EET DST 2001
+# Configuration time: Wed Jun 20 08:48:18 EET DST 2001
 # Configured by     : jhi
 # Target system     : osf1 alpha.hut.fi v4.0 878 alpha 
 
@@ -63,7 +63,7 @@ ccsymbols='__alpha=1 __LANGUAGE_C__=1 __osf__=1 __unix__=1 _LONGLONG=1 _SYSTYPE_
 ccversion='V5.6-082'
 cf_by='jhi'
 cf_email='yourname@yourhost.yourplace.com'
-cf_time='Fri Jun 15 02:15:37 EET DST 2001'
+cf_time='Wed Jun 20 08:48:18 EET DST 2001'
 charsize='1'
 chgrp=''
 chmod=''
@@ -85,7 +85,7 @@ cppstdin='cppstdin'
 cppsymbols='_AES_SOURCE=1 __alpha=1 __ALPHA=1 _ANSI_C_SOURCE=1 __LANGUAGE_C__=1 _LONGLONG=1 __osf__=1 _OSF_SOURCE=1 _POSIX_C_SOURCE=199506 _POSIX_SOURCE=1 _REENTRANT=1 __STDC__=1 _SYSTYPE_BSD=1 __unix__=1 _XOPEN_SOURCE=1'
 cryptlib=''
 csh='csh'
-d_Gconvert='gcvt((x),(n),(b))'
+d_Gconvert='sprintf((b),"%.*g",(n),(x))'
 d_PRIEUldbl='define'
 d_PRIFUldbl='define'
 d_PRIGUldbl='define'
@@ -287,7 +287,6 @@ d_quad='define'
 d_readdir='define'
 d_readlink='define'
 d_readv='define'
-d_realpath='define'
 d_recvmsg='define'
 d_rename='define'
 d_rewinddir='define'
@@ -438,7 +437,7 @@ eunicefix=':'
 exe_ext=''
 expr='expr'
 extensions='B ByteLoader Cwd DB_File Data/Dumper Devel/DProf Devel/Peek Digest/MD5 Encode Fcntl File/Glob Filter/Util/Call IO IPC/SysV List/Util MIME/Base64 NDBM_File ODBM_File Opcode POSIX PerlIO/Scalar PerlIO/Via SDBM_File Socket Storable Sys/Hostname Sys/Syslog Thread Time/HiRes Time/Piece XS/Typemap attrs re Errno'
-fflushNULL='undef'
+fflushNULL='define'
 fflushall='undef'
 find=''
 firstmakefile='makefile'
@@ -670,7 +669,7 @@ patchlevel='7'
 path_sep=':'
 perl5='/u/vieraat/vieraat/jhi/Perl/bin/perl'
 perl=''
-perl_patchlevel='10575'
+perl_patchlevel='10721'
 perladmin='yourname@yourhost.yourplace.com'
 perllibs='-lm -liconv -lutil -lpthread -lexc'
 perlpath='/opt/perl/bin/perl'
@@ -870,7 +869,7 @@ PERL_SUBVERSION=1
 PERL_API_REVISION=5
 PERL_API_VERSION=5
 PERL_API_SUBVERSION=0
-PERL_PATCHLEVEL=10575
+PERL_PATCHLEVEL=10721
 PERL_CONFIG_SH=true
 # Variables propagated from previous config.sh file.
 pp_sys_cflags='ccflags="$ccflags -DNO_EFF_ONLY_OK"'
index 9aea69c..b2c523d 100644 (file)
@@ -17,7 +17,7 @@
 /*
  * Package name      : perl5
  * Source directory  : .
- * Configuration time: Fri Jun 15 02:15:37 EET DST 2001
+ * Configuration time: Wed Jun 20 08:48:18 EET DST 2001
  * Configured by     : jhi
  * Target system     : osf1 alpha.hut.fi v4.0 878 alpha 
  */
  *     4 and 8. The default is eight, for safety.
  */
 #if defined(USE_CROSS_COMPILE) || defined(MULTIARCH)
-#define MEM_ALIGNBYTES 8
+#  define MEM_ALIGNBYTES 8
 #else
 #define MEM_ALIGNBYTES 8
 #endif
  *             d_Gconvert='sprintf((b),"%.*g",(n),(x))'
  *     The last two assume trailing zeros should not be kept.
  */
-#define Gconvert(x,n,t,b) gcvt((x),(n),(b))
+#define Gconvert(x,n,t,b) sprintf((b),"%.*g",(n),(x))
 
 /* HAS_GETCWD:
  *     This symbol, if defined, indicates that the getcwd routine is
  *     Note that if fflushNULL is defined, fflushall will not
  *     even be probed for and will be left undefined.
  */
-/*#define      FFLUSH_NULL             / **/
+#define        FFLUSH_NULL             /**/
 /*#define      FFLUSH_ALL              / **/
 
 /* Fpos_t:
  */
 /*#define      HAS_FLOCK_PROTO / **/
 
-/* HAS_REALPATH:
- *     This symbol, if defined, indicates that the realpath routine is
- *     available to do resolve paths.
- */
-#define HAS_REALPATH           /**/
-
 /* HAS_SIGPROCMASK:
  *     This symbol, if defined, indicates that the sigprocmask
  *     system call is available to examine or change the signal mask
index 35bfb1b..235369c 100644 (file)
@@ -3392,12 +3392,6 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
  */
 #$d_flockproto HAS_FLOCK_PROTO /**/
 
-/* HAS_REALPATH:
- *     This symbol, if defined, indicates that the realpath routine is
- *     available to do resolve paths.
- */
-#$d_realpath HAS_REALPATH              /**/
-
 /* HAS_SIGPROCMASK:
  *     This symbol, if defined, indicates that the sigprocmask
  *     system call is available to examine or change the signal mask
index 5f44ceb..64e0e5b 100755 (executable)
--- a/embed.pl
+++ b/embed.pl
@@ -2058,7 +2058,7 @@ Apd       |void   |sv_pos_b2u     |SV* sv|I32* offsetp
 Aopd   |char*  |sv_pvn_force   |SV* sv|STRLEN* lp
 Apd    |char*  |sv_pvutf8n_force|SV* sv|STRLEN* lp
 Apd    |char*  |sv_pvbyten_force|SV* sv|STRLEN* lp
-Apd    |int    |sv_realpath    |SV* sv|char *path|STRLEN len
+Apd    |int    |sv_realpath    |SV* sv|char *path|STRLEN maxlen
 Apd    |char*  |sv_reftype     |SV* sv|int ob
 Apd    |void   |sv_replace     |SV* sv|SV* nsv
 Apd    |void   |sv_report_used
index e910818..8c5901c 100644 (file)
--- a/perlapi.c
+++ b/perlapi.c
@@ -3172,9 +3172,9 @@ Perl_sv_pvbyten_force(pTHXo_ SV* sv, STRLEN* lp)
 
 #undef  Perl_sv_realpath
 int
-Perl_sv_realpath(pTHXo_ SV* sv, char *path, STRLEN len)
+Perl_sv_realpath(pTHXo_ SV* sv, char *path, STRLEN maxlen)
 {
-    return ((CPerlObj*)pPerl)->Perl_sv_realpath(sv, path, len);
+    return ((CPerlObj*)pPerl)->Perl_sv_realpath(sv, path, maxlen);
 }
 
 #undef  Perl_sv_reftype
index de8956b..75f9ec0 100644 (file)
@@ -3286,6 +3286,12 @@ assignment or as a subroutine argument for example).
 (F) Your Perl was compiled with B<-D>SETUID_SCRIPTS_ARE_SECURE_NOW, but
 a version of the setuid emulator somehow got run anyway.
 
+=item sv_realpath: %s
+
+(S) You probably used some form of getcwd.  The implementation of
+that functionality detected something odd in your filesystem
+environment and gave up (returning undef).
+
 =item Switch (?(condition)... contains too many branches in regex;
 
 marked by <-- HERE in m/%s/
index 1094d8c..0912724 100644 (file)
@@ -3908,7 +3908,7 @@ PUSHn, PUSHp, PUSHs, PUSHu, PUTBACK, Renew, Renewc, require_pv, RETVAL,
 Safefree, savepv, savepvn, SAVETMPS, SP, SPAGAIN, ST, strEQ, strGE, strGT,
 strLE, strLT, strNE, strnEQ, strnNE, StructCopy, SvCUR, SvCUR_set, SvEND,
 SvGETMAGIC, SvGROW, SvIOK, SvIOKp, SvIOK_notUV, SvIOK_off, SvIOK_on,
-SvIOK_only, SvIOK_only_UV, SvIOK_UV, SvIV, SvIVx, SvIVX, SvLEN, SvNIOK,
+SvIOK_only, SvIOK_only_UV, SvIOK_UV, SvIV, SvIVX, SvIVx, SvLEN, SvNIOK,
 SvNIOKp, SvNIOK_off, SvNOK, SvNOKp, SvNOK_off, SvNOK_on, SvNOK_only, SvNV,
 SvNVx, SvNVX, SvOK, SvOOK, SvPOK, SvPOKp, SvPOK_off, SvPOK_on, SvPOK_only,
 SvPOK_only_UTF8, SvPV, SvPVbyte, SvPVbytex, SvPVbytex_force,
@@ -4575,22 +4575,26 @@ I<The Road goes ever on and on, down from the door where it began.>
 
 =item Incompatible Changes
 
+=over 4
+
+=item 64-bit platforms and malloc
+
 =item Future Deprecations
 
+=back
+
 =item Core Enhancements
 
 =item Modules and Pragmata
 
 =over 4
 
-=item New Modules
+=item New Modules and Distribution
 
 =item Updated And Improved Modules and Pragmata
 
 =back
 
-=item Performance Enhancements
-
 =item Utility Changes
 
 =item New Documentation
@@ -4651,6 +4655,8 @@ I<The Road goes ever on and on, down from the door where it began.>
 
 =item Self-tying of Arrays and Hashes Is Forbidden
 
+=item Variable Attributes are not Currently Usable for Tieing
+
 =item Building Extensions Can Fail Because Of Largefiles
 
 =item The Compiler Suite Is Still Experimental
index 67578fa..4d51056 100644 (file)
--- a/uconfig.h
+++ b/uconfig.h
  *     4 and 8. The default is eight, for safety.
  */
 #if defined(USE_CROSS_COMPILE) || defined(MULTIARCH)
-#define MEM_ALIGNBYTES 8
+#  define MEM_ALIGNBYTES 8
 #else
 #define MEM_ALIGNBYTES 4
 #endif
  */
 /*#define      HAS_FLOCK_PROTO / **/
 
-/* HAS_REALPATH:
- *     This symbol, if defined, indicates that the realpath routine is
- *     available to do resolve paths.
- */
-/*#define HAS_REALPATH         / **/
-
 /* HAS_SIGPROCMASK:
  *     This symbol, if defined, indicates that the sigprocmask
  *     system call is available to examine or change the signal mask
index 52e34b7..ca35351 100755 (executable)
@@ -218,7 +218,6 @@ d_quad='undef'
 d_readdir='undef'
 d_readlink='undef'
 d_readv='undef'
-d_realpath='undef'
 d_recvmsg='undef'
 d_rename='undef'
 d_rewinddir='undef'
diff --git a/util.c b/util.c
index 02c907d..1d69fe5 100644 (file)
--- a/util.c
+++ b/util.c
@@ -3624,6 +3624,9 @@ Perl_sv_getcwd(pTHX_ register SV *sv)
 
     SvGROW(sv, 128);
     while ((getcwd(SvPVX(sv), SvLEN(sv)-1) == NULL) && errno == ERANGE) {
+        if (SvLEN(sv) + 128 >= MAXPATHLEN) {
+            SV_CWD_RETURN_UNDEF;
+       }
         SvGROW(sv, SvLEN(sv) + 128);
     }
     SvCUR_set(sv, strlen(SvPVX(sv)));
@@ -3687,6 +3690,10 @@ Perl_sv_getcwd(pTHX_ register SV *sv)
             SV_CWD_RETURN_UNDEF;
         }
 
+        if (pathlen + namelen + 1 >= MAXPATHLEN) {
+            SV_CWD_RETURN_UNDEF;
+       }
+
         SvGROW(sv, pathlen + namelen + 1);
 
         if (pathlen) {
@@ -3737,62 +3744,44 @@ Perl_sv_getcwd(pTHX_ register SV *sv)
 /*
 =for apidoc sv_realpath
 
-Wrap or emulate realpath(3).
+Emulate realpath(3).
+
+The real realpath() is not used because it's a known can of worms.
+We may have bugs but hey, they are our very own.
 
 =cut
  */
 int
-Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len)
+Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN maxlen)
 {
 #ifndef PERL_MICRO
-    char name[MAXPATHLEN] = { 0 }, *s;
+    char name[MAXPATHLEN]    = { 0 };
+    char dotdots[MAXPATHLEN] = { 0 };
+    char *s;
     STRLEN pathlen, namelen;
+    DIR *parent;
+    Direntry_t *dp;
+    struct stat cst, pst, tst;
 
-    /* Don't use strlen() to avoid running off the end. */
-    s = memchr(path, '\0', MAXPATHLEN);
-    pathlen = s ? s - path : MAXPATHLEN;
-
-#ifdef HAS_REALPATH
-
-    /* Be paranoid about the use of realpath(),
-     * it is an infamous source of buffer overruns. */
-
-    /* Is the source buffer too long? */
-    if (pathlen == MAXPATHLEN) {
-        Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %c= (MAXPATHLEN = %d)",
-                  path, s ? '=' : '>', MAXPATHLEN);
-        SV_CWD_RETURN_UNDEF;
-    }
-
-    /* Here goes nothing. */
-    if (realpath(path, name) == NULL) {
-        Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %s",
-                  path, Strerror(errno));
+    if (!sv || !path || !maxlen) {
+        Perl_warn(aTHX_ "sv_realpath: realpath(0x%x, 0x%x, "")",
+                  sv, path, maxlen);
         SV_CWD_RETURN_UNDEF;
     }
 
-    /* Is the destination buffer too long?
+    /* Is the source buffer too long?
      * Don't use strlen() to avoid running off the end. */
-    s = memchr(name, '\0', MAXPATHLEN);
-    namelen = s ? s - name : MAXPATHLEN;
-    if (namelen == MAXPATHLEN) {
-        Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %c= (MAXPATHLEN = %d)",
-                  path, s ? '=' : '>', MAXPATHLEN);
+    if (maxlen >= MAXPATHLEN)
+        pathlen = maxlen;
+    else {
+        s = memchr(path, '\0', MAXPATHLEN);
+       pathlen = s ? s - path : MAXPATHLEN;
+    }
+    if (pathlen >= MAXPATHLEN) {
+        Perl_warn(aTHX_ "sv_realpath: source too large");
         SV_CWD_RETURN_UNDEF;
     }
 
-    /* The coast is clear? */
-    sv_setpvn(sv, name, namelen);
-    SvPOK_only(sv);
-
-    return TRUE;
-#else
-    {
-    DIR *parent;
-    Direntry_t *dp;
-    char dotdots[MAXPATHLEN] = { 0 };
-    struct stat cst, pst, tst;
-
     if (PerlLIO_stat(path, &cst) < 0) {
         Perl_warn(aTHX_ "sv_realpath: stat(\"%s\"): %s",
                   path, Strerror(errno));
@@ -3801,10 +3790,9 @@ Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len)
 
     (void)SvUPGRADE(sv, SVt_PV);
 
-    if (!len) {
-        len = strlen(path);
-    }
-    Copy(path, dotdots, len, char);
+    Copy(path, dotdots, maxlen, char);
+
+    pathlen = 0;
 
     for (;;) {
         strcat(dotdots, "/..");
@@ -3864,6 +3852,11 @@ Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len)
                 SV_CWD_RETURN_UNDEF;
             }
 
+           if (pathlen + namelen + 1 >= MAXPATHLEN) {
+               Perl_warn(aTHX_ "sv_realpath: too long name");
+                SV_CWD_RETURN_UNDEF;
+           }
+
             SvGROW(sv, pathlen + namelen + 1);
             if (pathlen) {
                 /* shift down */
@@ -3890,10 +3883,8 @@ Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len)
     SvPOK_only(sv);
 
     return TRUE;
-    }
-#endif
 #else
-    return FALSE;
+    return FALSE; /* MICROPERL */
 #endif
 }
 
index 2319650..0065516 100644 (file)
@@ -194,7 +194,6 @@ $d_quad='undef'
 $d_readdir='define'
 $d_readlink='define'
 $d_readv='undef'
-$d_realpath='undef'
 $d_recvmsg='undef'
 $d_rename='define'
 $d_rewinddir='define'
index 54dfc0c..3f47acf 100644 (file)
  */
 /*#define      HAS_FLOCK_PROTO /**/
 
-/* HAS_REALPATH:
- *     This symbol, if defined, indicates that the realpath routine is
- *     available to do resolve paths.
- */
-/*#define HAS_REALPATH         /**/
-
 /* HAS_SIGPROCMASK:
  *     This symbol, if defined, indicates that the sigprocmask
  *     system call is available to examine or change the signal mask
index 9a0a02c..4d49cf5 100644 (file)
@@ -194,7 +194,6 @@ $d_quad='undef'
 $d_readdir='define'
 $d_readlink='define'
 $d_readv='undef'
-$d_realpath='undef'
 $d_recvmsg='undef'
 $d_rename='define'
 $d_rewinddir='define'
index 8c4dd35..5b283e3 100644 (file)
  */
 /*#define      HAS_FLOCK_PROTO /**/
 
-/* HAS_REALPATH:
- *     This symbol, if defined, indicates that the realpath routine is
- *     available to do resolve paths.
- */
-/*#define HAS_REALPATH         /**/
-
 /* HAS_SIGPROCMASK:
  *     This symbol, if defined, indicates that the sigprocmask
  *     system call is available to examine or change the signal mask
index 6efd9ca..6f1d3c1 100644 (file)
  */
 /*#define      HAS_FLOCK_PROTO /**/
 
-/* HAS_REALPATH:
- *     This symbol, if defined, indicates that the realpath routine is
- *     available to do resolve paths.
- */
-/*#define HAS_REALPATH         /**/
-
 /* HAS_SIGPROCMASK:
  *     This symbol, if defined, indicates that the sigprocmask
  *     system call is available to examine or change the signal mask
index 0f20bce..ce85240 100644 (file)
  */
 /*#define      HAS_FLOCK_PROTO /**/
 
-/* HAS_REALPATH:
- *     This symbol, if defined, indicates that the realpath routine is
- *     available to do resolve paths.
- */
-/*#define HAS_REALPATH         /**/
-
 /* HAS_SIGPROCMASK:
  *     This symbol, if defined, indicates that the sigprocmask
  *     system call is available to examine or change the signal mask
index 476245e..e48c157 100644 (file)
  */
 /*#define      HAS_FLOCK_PROTO /**/
 
-/* HAS_REALPATH:
- *     This symbol, if defined, indicates that the realpath routine is
- *     available to do resolve paths.
- */
-/*#define HAS_REALPATH         /**/
-
 /* HAS_SIGPROCMASK:
  *     This symbol, if defined, indicates that the sigprocmask
  *     system call is available to examine or change the signal mask