~ chicken-core (chicken-5) cde395398877f1ec984e3a38f8bd810926f23be2


commit cde395398877f1ec984e3a38f8bd810926f23be2
Author:     Evan Hanson <evhan@foldling.org>
AuthorDate: Tue Jul 21 22:19:45 2015 +1200
Commit:     Peter Bex <peter@more-magic.net>
CommitDate: Wed Jul 22 15:00:55 2015 +0200

    Fix normalize-pathname for dot-relative paths beginning with ".//"
    
    Because dots aren't pushed onto the accumulated list of pathname parts,
    `normalize-pathname` would hit the second slash, see that there were no
    leading parts, and consider the path absolute.
    
    To fix this, we make the function save the type of the path, either
    'abs(olute) or 'rel(ative), as soon as it's known, and avoid overwriting
    it from then on.
    
    Fixes #1202.
    
    Signed-off-by: Peter Bex <peter@more-magic.net>

diff --git a/NEWS b/NEWS
index 8eb4e48e..bb9d1fce 100644
--- a/NEWS
+++ b/NEWS
@@ -35,6 +35,10 @@
 - Unit lolevel:
   - Restore long-lost but still documented "vector-like?" procedure (#983)
 
+- Unit "files":
+  - normalize-pathname no longer considers paths starting with ".//"
+    as absolute (#1202, reported by Haochi Kiang).
+
 - Unit "posix":
   - set-file-position! now allows negative positions for seek/cur (thanks
     to Seth Alves).
diff --git a/files.scm b/files.scm
index af437d1a..59de9610 100644
--- a/files.scm
+++ b/files.scm
@@ -363,17 +363,15 @@ EOF
       (let ((sep (if (eq? platform 'windows) #\\ #\/)))
 	(##sys#check-string path 'normalize-pathname)
 	(let ((len (##sys#size path))
-	      (abspath #f)
+	      (type #f)
 	      (drive #f))
 	  (let loop ((i 0) (prev 0) (parts '()))
 	    (cond ((fx>= i len)
 		   (when (fx> i prev)
 		     (set! parts (addpart (##sys#substring path prev i) parts)))
 		   (if (null? parts)
-		       (let ((r (if abspath (string sep) ".")))
-			 (if drive
-			     (##sys#string-append drive r)
-			     r))
+		       (let ((r (if (eq? type 'abs) (string sep) ".")))
+			 (if drive (##sys#string-append drive r) r))
 		       (let ((out (open-output-string))
 			     (parts (##sys#fast-reverse parts)))
 			 (display (car parts) out)
@@ -384,14 +382,14 @@ EOF
 			  (cdr parts))
 			 (when (fx= i prev) (##sys#write-char-0 sep out))
 			 (let ((r (get-output-string out)))
-                           (when abspath
-                             (set! r (##sys#string-append (string sep) r)))
-                           (when drive
-                             (set! r (##sys#string-append drive r)))
-                           r))))
+			   (when (eq? type 'abs)
+			     (set! r (##sys#string-append (string sep) r)))
+			   (when drive
+			     (set! r (##sys#string-append drive r)))
+			   r))))
 		  ((*char-pds? (string-ref path i))
-		   (when (and (null? parts) (fx= i prev))
-		     (set! abspath #t))
+		   (when (not type)
+		     (set! type (if (fx= i prev) 'abs 'rel)))
 		   (if (fx= i prev)
 		       (loop (fx+ i 1) (fx+ i 1) parts)
 		       (loop (fx+ i 1)
diff --git a/tests/path-tests.scm b/tests/path-tests.scm
index 1af196b6..6e66fa66 100644
--- a/tests/path-tests.scm
+++ b/tests/path-tests.scm
@@ -31,6 +31,8 @@
 (test "/" (normalize-pathname "/./" 'unix))
 (test "/" (normalize-pathname "/./." 'unix))
 (test "." (normalize-pathname "./" 'unix))
+(test "a" (normalize-pathname "./a"))
+(test "a" (normalize-pathname ".///a"))
 (test "a" (normalize-pathname "a"))
 (test "a/" (normalize-pathname "a/" 'unix))
 (test "a/b" (normalize-pathname "a/b" 'unix))
Trap