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

2 views
Skip to first unread message

Greg Ward

unread,
Mar 21, 2012, 8:38:13 PM3/21/12
to mercuri...@selenic.com
# HG changeset patch
# User Greg Ward <gr...@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@Ke#VqoykDzRh04j8#`NT7pJb))Jq)X5Eyy`$=eojM+dhSR^3+@~`O
xY&Gq*Tcpdm+)w4>CpL(rJVG5W17G+x=V>!}{~YYC+iiDPMtj+*xJot*^8j}D7cBq)

_______________________________________________
Mercurial-devel mailing list
Mercuri...@selenic.com
http://selenic.com/mailman/listinfo/mercurial-devel

Mads Kiilerich

unread,
Mar 21, 2012, 10:14:36 PM3/21/12
to Greg Ward, mercuri...@selenic.com
Greg Ward wrote, On 03/22/2012 01:38 AM:
> # HG changeset patch
> # User Greg Ward<gr...@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. ;-)

It has previously been proposed that we just could store the lower bits
of the file size in the dirstate. That should be sufficiently safe for
most real world usage.

Something similar could perhaps be done with the time stamp.

/Mads

Reply all
Reply to author
Forward
0 new messages