Rev 4556: Fix bug #394227, osutils.relpath() could get into an infinite loop. in http://bazaar.launchpad.net/~jameinel/bzr/1.18-relpath-394227

John Arbash Meinel john at arbash-meinel.com
Wed Jul 22 17:41:57 BST 2009


At http://bazaar.launchpad.net/~jameinel/bzr/1.18-relpath-394227

------------------------------------------------------------
revno: 4556
revision-id: john at arbash-meinel.com-20090722164148-uv3t6ath2t2tlo68
parent: pqm at pqm.ubuntu.com-20090720145231-zntxtpyaoujmkrsz
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 1.18-relpath-394227
timestamp: Wed 2009-07-22 11:41:48 -0500
message:
  Fix bug #394227, osutils.relpath() could get into an infinite loop.
  
  If your current path was at the root of a drive (like 'C:/', and you did something
  like 'bzr init-repo H:/repo', then the relpath code would spin forever, trying
  to find the relative path to H:/repo from C:/. The problem was that
  os.path.split() doesn't strip off the drive letter, so you end up comparing
  C:/ to H:/, and neither is 'shorter' to say that we didn't match.
-------------- next part --------------
=== modified file 'NEWS'
--- a/NEWS	2009-07-20 11:27:05 +0000
+++ b/NEWS	2009-07-22 16:41:48 +0000
@@ -51,6 +51,12 @@
   lots of backtraces about ``UnknownSmartMethod``, ``do_chunk`` or
   ``do_end``.  (Andrew Bennetts, #338561)
   
+* There was a bug in ``osutils.relpath`` that was only triggered on
+  Windows. Essentially if you were at the root of a drive, and did
+  something to a branch/repo on another drive, we would go into an
+  infinite loop while trying to find a 'relative path'.
+  (John Arbash Meinel, #394227)
+
 * ``WorkingTree4.unversion`` will no longer fail to unversion ids which
   were present in a parent tree but renamed in the working tree.
   (Robert Collins, #187207)

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2009-07-08 14:37:25 +0000
+++ b/bzrlib/osutils.py	2009-07-22 16:41:48 +0000
@@ -1040,14 +1040,14 @@
 
     s = []
     head = rp
-    while len(head) >= len(base):
+    while True:
+        if len(head) <= len(base) and head != base:
+            raise errors.PathNotChild(rp, base)
         if head == base:
             break
-        head, tail = os.path.split(head)
+        head, tail = split(head)
         if tail:
-            s.insert(0, tail)
-    else:
-        raise errors.PathNotChild(rp, base)
+            s.append(tail)
 
     if s:
         return pathjoin(*s)

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2009-06-30 04:13:19 +0000
+++ b/bzrlib/tests/test_osutils.py	2009-07-22 16:41:48 +0000
@@ -625,6 +625,20 @@
         self.assertEqual("1234", output.getvalue())
 
 
+class TestRelpath(tests.TestCase):
+
+    def test_simple_relpath(self):
+        cwd = osutils.getcwd()
+        subdir = cwd + '/subdir'
+        self.assertEqual('subdir', osutils.relpath(cwd, subdir))
+
+    def test_not_relative(self):
+        self.assertRaises(errors.PathNotChild,
+                          osutils.relpath, 'C:/path', 'H:/path')
+        self.assertRaises(errors.PathNotChild,
+                          osutils.relpath, 'C:/', 'H:/path')
+
+
 class TestSafeUnicode(tests.TestCase):
 
     def test_from_ascii_string(self):



More information about the bazaar-commits mailing list