? path.patch
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.360
diff -u -r1.360 ChangeLog
--- ChangeLog	2000/12/14 22:24:45	1.360
+++ ChangeLog	2001/01/04 01:25:17
@@ -1,5 +1,15 @@
-2000-12-14  Don Porter  <dgp@users.sourceforge.net>
+2001-01-xx  Don Porter  <dgp@users.sourceforge.net>
+	* tests/unixInit.test:
+	* unix/tclUnixInit.c (TclpInitLibraryPath):
+	* win/tclWinInit.c (TclpInitLibraryPath):  Several entries in
+	the library path ($tcl_libPath) are determined relative to the
+	absolute path of the executable.  When the executable is
+	installed in or near the root directory of the file system,
+	relative pathnames were being incorrectly generated, and in
+	the worst case, memory access violations were crashing the program.
+	[Bug 119416, Patch 102972]
 
+2000-12-14  Don Porter  <dgp@users.sourceforge.net>
 	* generic/tclExecute.c:
 	* tests/expr-old.test:  Re-wrote Tcl's [expr rand()] and
 	[expr srand($seed)] implementations, fixing a range error
Index: tests/unixInit.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/unixInit.test,v
retrieving revision 1.13
diff -u -r1.13 unixInit.test
--- tests/unixInit.test	2000/04/10 17:19:05	1.13
+++ tests/unixInit.test	2001/01/04 01:25:17
@@ -150,6 +150,24 @@
     # would need test command to get defaultLibDir and compare it to
     # [lindex $auto_path end]
 } {}
+test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} {unixOnly} {
+    file delete -force /tmp/sparkly
+    file delete -force /tmp/lib
+    file mkdir /tmp/sparkly
+    file copy $::tcltest::tcltest /tmp/sparkly/tcltest
+
+    file mkdir /tmp/lib/tcl[info tclversion]
+    close [open /tmp/lib/tcl[info tclversion]/init.tcl w]
+
+    set allAbsolute 1
+    foreach dir [getlibpath /tmp/sparkly/tcltest] {
+	set allAbsolute [expr {$allAbsolute \
+		&& [string equal absolute [file pathtype $dir]]}]
+    }
+    file delete -force /tmp/sparkly
+    file delete -force /tmp/lib
+    set allAbsolute
+} 1
 test unixInit-3.1 {TclpSetInitialEncodings} {unixOnly installedTcl} {
     set env(LANG) C
 
Index: unix/tclUnixInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixInit.c,v
retrieving revision 1.20
diff -u -r1.20 tclUnixInit.c
--- unix/tclUnixInit.c	2000/10/31 00:48:53	1.20
+++ unix/tclUnixInit.c	2001/01/04 01:25:17
@@ -281,44 +281,50 @@
      *		(e.g. /usr/src/tcl8.2/unix/solaris-sparc/../../../tcl8.2/library)
      */
      
+
+     /*
+      * The variable path holds an absolute path.  Take care not to
+      * overwrite pathv[0] since that might produce a relative path.
+      */
+
     if (path != NULL) {
 	Tcl_SplitPath(path, &pathc, &pathv);
-	if (pathc > 1) {
+	if (pathc > 2) {
 	    pathv[pathc - 2] = installLib;
 	    path = Tcl_JoinPath(pathc - 1, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 2) {
+	if (pathc > 3) {
 	    pathv[pathc - 3] = installLib;
 	    path = Tcl_JoinPath(pathc - 2, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 1) {
+	if (pathc > 2) {
 	    pathv[pathc - 2] = "library";
 	    path = Tcl_JoinPath(pathc - 1, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 2) {
+	if (pathc > 3) {
 	    pathv[pathc - 3] = "library";
 	    path = Tcl_JoinPath(pathc - 2, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 1) {
+	if (pathc > 3) {
 	    pathv[pathc - 3] = developLib;
 	    path = Tcl_JoinPath(pathc - 2, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 3) {
+	if (pathc > 4) {
 	    pathv[pathc - 4] = developLib;
 	    path = Tcl_JoinPath(pathc - 3, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
Index: win/tclWinInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinInit.c,v
retrieving revision 1.24
diff -u -r1.24 tclWinInit.c
--- win/tclWinInit.c	2000/07/26 01:27:58	1.24
+++ win/tclWinInit.c	2001/01/04 01:25:17
@@ -229,44 +229,49 @@
      *		(e.g. /usr/src/tcl8.2/unix/solaris-sparc/../../../tcl8.2/library)
      */
      
+    /*
+     * The variable path holds an absolute path.  Take care not to
+     * overwrite pathv[0] since that might produce a relative path.
+     */
+
     if (path != NULL) {
 	Tcl_SplitPath(path, &pathc, &pathv);
-	if (pathc > 1) {
+	if (pathc > 2) {
 	    pathv[pathc - 2] = installLib;
 	    path = Tcl_JoinPath(pathc - 1, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 2) {
+	if (pathc > 3) {
 	    pathv[pathc - 3] = installLib;
 	    path = Tcl_JoinPath(pathc - 2, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 1) {
+	if (pathc > 2) {
 	    pathv[pathc - 2] = "library";
 	    path = Tcl_JoinPath(pathc - 1, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 2) {
+	if (pathc > 3) {
 	    pathv[pathc - 3] = "library";
 	    path = Tcl_JoinPath(pathc - 2, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 1) {
+	if (pathc > 3) {
 	    pathv[pathc - 3] = developLib;
 	    path = Tcl_JoinPath(pathc - 2, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
 	    Tcl_DStringFree(&ds);
 	}
-	if (pathc > 3) {
+	if (pathc > 4) {
 	    pathv[pathc - 4] = developLib;
 	    path = Tcl_JoinPath(pathc - 3, pathv, &ds);
 	    objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
