Validate paths before reading or writing files in repository or working dir.
authorThomas Arendsen Hein <thomas@intevation.de>
Sat, 04 Mar 2006 19:01:45 +0100
changeset 1835 bdfb524d728a
parent 1834 24881eaebee3
child 1836 cd5c1db2132a
Validate paths before reading or writing files in repository or working dir. Fixes security relevant issue134.
mercurial/commands.py
mercurial/localrepo.py
mercurial/util.py
--- a/mercurial/commands.py	Fri Mar 03 13:41:12 2006 -0800
+++ b/mercurial/commands.py	Sat Mar 04 19:01:45 2006 +0100
@@ -1014,7 +1014,7 @@
 
 def debugancestor(ui, index, rev1, rev2):
     """find the ancestor revision of two revisions in a given index"""
-    r = revlog.revlog(util.opener(os.getcwd()), index, "")
+    r = revlog.revlog(util.opener(os.getcwd(), audit=False), index, "")
     a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
     ui.write("%d:%s\n" % (r.rev(a), hex(a)))
 
@@ -1100,7 +1100,8 @@
 
 def debugdata(ui, file_, rev):
     """dump the contents of an data file revision"""
-    r = revlog.revlog(util.opener(os.getcwd()), file_[:-2] + ".i", file_)
+    r = revlog.revlog(util.opener(os.getcwd(), audit=False),
+                      file_[:-2] + ".i", file_)
     try:
         ui.write(r.revision(r.lookup(rev)))
     except KeyError:
@@ -1108,7 +1109,7 @@
 
 def debugindex(ui, file_):
     """dump the contents of an index file"""
-    r = revlog.revlog(util.opener(os.getcwd()), file_, "")
+    r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "")
     ui.write("   rev    offset  length   base linkrev" +
              " nodeid       p1           p2\n")
     for i in range(r.count()):
@@ -1119,7 +1120,7 @@
 
 def debugindexdot(ui, file_):
     """dump an index DAG as a .dot file"""
-    r = revlog.revlog(util.opener(os.getcwd()), file_, "")
+    r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "")
     ui.write("digraph G {\n")
     for i in range(r.count()):
         e = r.index[i]
--- a/mercurial/localrepo.py	Fri Mar 03 13:41:12 2006 -0800
+++ b/mercurial/localrepo.py	Sat Mar 04 19:01:45 2006 +0100
@@ -1679,6 +1679,7 @@
         remove.sort()
         for f in remove:
             self.ui.note(_("removing %s\n") % f)
+            util.audit_path(f)
             try:
                 util.unlink(self.wjoin(f))
             except OSError, inst:
--- a/mercurial/util.py	Fri Mar 03 13:41:12 2006 -0800
+++ b/mercurial/util.py	Sat Mar 04 19:01:45 2006 +0100
@@ -363,7 +363,14 @@
         else:
             shutil.copy(src, dst)
 
-def opener(base):
+def audit_path(path):
+    """Abort if path contains dangerous components"""
+    parts = os.path.normcase(path).split(os.sep)
+    if (os.path.splitdrive(path)[0] or parts[0] in ('.hg', '')
+        or os.pardir in parts):
+        raise Abort(_("path contains illegal component: %s\n") % path)
+
+def opener(base, audit=True):
     """
     return a function that opens files relative to base
 
@@ -371,6 +378,7 @@
     remote file access from higher level code.
     """
     p = base
+    audit_p = audit
 
     def mktempcopy(name):
         d, fn = os.path.split(name)
@@ -401,6 +409,8 @@
             self.close()
 
     def o(path, mode="r", text=False, atomic=False):
+        if audit_p:
+            audit_path(path)
         f = os.path.join(p, path)
 
         if not text: