[PATCH RFC STABLE?] dirstate: catch non-32-bit-safe mtime and file size early (issue2608)

Greg Ward greg at gerg.ca
Wed Mar 21 19:38:13 CDT 2012


# HG changeset patch
# User Greg Ward <greg at gerg.ca>
# Date 1329327653 18000
# Branch stable
# Node ID 354794e7bf7fd4713bd5f46ce9770c7ae1b4f7ad
# Parent  9670e0c88deee8dcfe45ddb3010696928b835fec
dirstate: catch non-32-bit-safe mtime and file size early (issue2608).

Rather than blow up late in the game, after we've already committed
and are just trying to write the dirstate, catch it much earlier. Then
we avoid putting the working dir in a bad state (dirstate does not
reflect commit), and it's also quite obvious that the problem is that
some file has blown one of the 32-bit limits in dirstate.

Error messages need work. Commence bikeshedding at will. ;-)

diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -46,6 +46,16 @@
             return
         del dirs[base]
 
+_toobig = 2**31
+def _lstat(fn):
+    '''wrapper for os.lstat() to ensure the size and mtime are 32-bit safe,
+    i.e. won't make dirstate.write() blow up with struct.error'''
+    s = os.lstat(fn)
+    if s.st_size >= _toobig:
+        raise util.Abort('file %s too big for dirstate' % fn)
+    if s.st_mtime >= _toobig:
+        raise util.Abort('file %s too new for dirstate' % fn)
+
 class dirstate(object):
 
     def __init__(self, opener, ui, root, validate):
@@ -308,7 +318,7 @@
         '''Mark a file normal and clean.'''
         self._dirty = True
         self._addpath(f)
-        s = os.lstat(self._join(f))
+        s = _lstat(self._join(f))
         mtime = int(s.st_mtime)
         self._map[f] = ('n', s.st_mode, s.st_size, mtime)
         if f in self._copymap:
@@ -356,6 +366,7 @@
 
     def add(self, f):
         '''Mark a file added.'''
+        _lstat(f)               # trigger the 32-bit safety check
         self._dirty = True
         self._addpath(f, True)
         self._map[f] = ('a', 0, -1, -1)
@@ -381,7 +392,7 @@
     def merge(self, f):
         '''Mark a file merged.'''
         self._dirty = True
-        s = os.lstat(self._join(f))
+        s = _lstat(self._join(f))
         self._addpath(f)
         self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
         if f in self._copymap:
diff --git a/tests/gpg/trustdb.gpg b/tests/gpg/trustdb.gpg
index 4008cdab6dbf5976ed84e1bd48fd954edd0bd6df..826f03e0e42de51482d52fc6fc87e9eababd9589
GIT binary patch
literal 1280
zc${NQFGy!*W at Ke#VqoykDzRh04j8#`NT7pJb))Jq)X5Eyy`$=eojM+dhSR^3+@~`O
xY&Gq*Tcpdm+)w4>CpL(rJVG5W17G+x=V>!}{~YYC+iiDPMtj+*xJot*^8j}D7cBq)



More information about the Mercurial-devel mailing list