comparison mercurial/revlog.py @ 25410:eee88912db0a

revlog: raise an exception earlier if an entry is too large (issue4675) Before we were relying on _pack to error out when trying to pass an integer that was too large for the "i" format specifier. Now we check this earlier so we can form a better error message. The error message unfortunately must exclude the filename at this level of the call stack. The problem is that this name is not available here, and the error can be triggered by a large manifest or by a large file itself. Although perhaps we could provide the name of a revlog index file (from the revlog object, instead of the revlogio object), this seems like too much leakage of internal data structures. It's not ideal already that an error message even mentions revlogs, but this does seem unavoidable here.
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Tue, 02 Jun 2015 15:04:39 -0400
parents 1635579f9baf
children 0bda5bfaf0b1
comparison
equal deleted inserted replaced
25409:95e042d77a5f 25410:eee88912db0a
151 # 32 bytes: nodeid 151 # 32 bytes: nodeid
152 indexformatng = ">Qiiiiii20s12x" 152 indexformatng = ">Qiiiiii20s12x"
153 ngshaoffset = 32 153 ngshaoffset = 32
154 versionformat = ">I" 154 versionformat = ">I"
155 155
156 # corresponds to uncompressed length of indexformatng (2 gigs, 4-byte
157 # signed integer)
158 _maxentrysize = 0x7fffffff
159
156 class revlogio(object): 160 class revlogio(object):
157 def __init__(self): 161 def __init__(self):
158 self.size = struct.calcsize(indexformatng) 162 self.size = struct.calcsize(indexformatng)
159 163
160 def parseindex(self, data, inline): 164 def parseindex(self, data, inline):
161 # call the C implementation to parse the index data 165 # call the C implementation to parse the index data
162 index, cache = parsers.parse_index2(data, inline) 166 index, cache = parsers.parse_index2(data, inline)
163 return index, getattr(index, 'nodemap', None), cache 167 return index, getattr(index, 'nodemap', None), cache
164 168
165 def packentry(self, entry, node, version, rev): 169 def packentry(self, entry, node, version, rev):
170 uncompressedlength = entry[2]
171 if uncompressedlength > _maxentrysize:
172 raise RevlogError(
173 _("size of %d bytes exceeds maximum revlog storage of 2GiB")
174 % uncompressedlength)
175
166 p = _pack(indexformatng, *entry) 176 p = _pack(indexformatng, *entry)
167 if rev == 0: 177 if rev == 0:
168 p = _pack(versionformat, version) + p[4:] 178 p = _pack(versionformat, version) + p[4:]
169 return p 179 return p
170 180