##// END OF EJS Templates
parsers.c: fix integer overflows...
Benoit Boissinot -
r7174:4da87407 default
parent child Browse files
Show More
@@ -1,425 +1,433 b''
1 /*
1 /*
2 parsers.c - efficient content parsing
2 parsers.c - efficient content parsing
3
3
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
7 the GNU General Public License, incorporated herein by reference.
8 */
8 */
9
9
10 #include <Python.h>
10 #include <Python.h>
11 #include <ctype.h>
11 #include <ctype.h>
12 #include <string.h>
12 #include <string.h>
13
13
14 static int hexdigit(char c)
14 static int hexdigit(char c)
15 {
15 {
16 if (c >= '0' && c <= '9')
16 if (c >= '0' && c <= '9')
17 return c - '0';
17 return c - '0';
18 if (c >= 'a' && c <= 'f')
18 if (c >= 'a' && c <= 'f')
19 return c - 'a' + 10;
19 return c - 'a' + 10;
20 if (c >= 'A' && c <= 'F')
20 if (c >= 'A' && c <= 'F')
21 return c - 'A' + 10;
21 return c - 'A' + 10;
22
22
23 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
23 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
24 return 0;
24 return 0;
25 }
25 }
26
26
27 /*
27 /*
28 * Turn a hex-encoded string into binary.
28 * Turn a hex-encoded string into binary.
29 */
29 */
30 static PyObject *unhexlify(const char *str, int len)
30 static PyObject *unhexlify(const char *str, int len)
31 {
31 {
32 PyObject *ret;
32 PyObject *ret;
33 const char *c;
33 const char *c;
34 char *d;
34 char *d;
35
35
36 ret = PyString_FromStringAndSize(NULL, len / 2);
36 ret = PyString_FromStringAndSize(NULL, len / 2);
37 if (!ret)
37 if (!ret)
38 return NULL;
38 return NULL;
39
39
40 d = PyString_AS_STRING(ret);
40 d = PyString_AS_STRING(ret);
41 for (c = str; c < str + len;) {
41 for (c = str; c < str + len;) {
42 int hi = hexdigit(*c++);
42 int hi = hexdigit(*c++);
43 int lo = hexdigit(*c++);
43 int lo = hexdigit(*c++);
44 *d++ = (hi << 4) | lo;
44 *d++ = (hi << 4) | lo;
45 }
45 }
46
46
47 return ret;
47 return ret;
48 }
48 }
49
49
50 /*
50 /*
51 * This code assumes that a manifest is stitched together with newline
51 * This code assumes that a manifest is stitched together with newline
52 * ('\n') characters.
52 * ('\n') characters.
53 */
53 */
54 static PyObject *parse_manifest(PyObject *self, PyObject *args)
54 static PyObject *parse_manifest(PyObject *self, PyObject *args)
55 {
55 {
56 PyObject *mfdict, *fdict;
56 PyObject *mfdict, *fdict;
57 char *str, *cur, *start, *zero;
57 char *str, *cur, *start, *zero;
58 int len;
58 int len;
59
59
60 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
60 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
61 &PyDict_Type, &mfdict,
61 &PyDict_Type, &mfdict,
62 &PyDict_Type, &fdict,
62 &PyDict_Type, &fdict,
63 &str, &len))
63 &str, &len))
64 goto quit;
64 goto quit;
65
65
66 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
66 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
67 PyObject *file = NULL, *node = NULL;
67 PyObject *file = NULL, *node = NULL;
68 PyObject *flags = NULL;
68 PyObject *flags = NULL;
69 int nlen;
69 int nlen;
70
70
71 if (!*cur) {
71 if (!*cur) {
72 zero = cur;
72 zero = cur;
73 continue;
73 continue;
74 }
74 }
75 else if (*cur != '\n')
75 else if (*cur != '\n')
76 continue;
76 continue;
77
77
78 if (!zero) {
78 if (!zero) {
79 PyErr_SetString(PyExc_ValueError,
79 PyErr_SetString(PyExc_ValueError,
80 "manifest entry has no separator");
80 "manifest entry has no separator");
81 goto quit;
81 goto quit;
82 }
82 }
83
83
84 file = PyString_FromStringAndSize(start, zero - start);
84 file = PyString_FromStringAndSize(start, zero - start);
85 if (!file)
85 if (!file)
86 goto bail;
86 goto bail;
87
87
88 nlen = cur - zero - 1;
88 nlen = cur - zero - 1;
89
89
90 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
90 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
91 if (!node)
91 if (!node)
92 goto bail;
92 goto bail;
93
93
94 if (nlen > 40) {
94 if (nlen > 40) {
95 PyObject *flags;
95 PyObject *flags;
96
96
97 flags = PyString_FromStringAndSize(zero + 41,
97 flags = PyString_FromStringAndSize(zero + 41,
98 nlen - 40);
98 nlen - 40);
99 if (!flags)
99 if (!flags)
100 goto bail;
100 goto bail;
101
101
102 if (PyDict_SetItem(fdict, file, flags) == -1)
102 if (PyDict_SetItem(fdict, file, flags) == -1)
103 goto bail;
103 goto bail;
104 }
104 }
105
105
106 if (PyDict_SetItem(mfdict, file, node) == -1)
106 if (PyDict_SetItem(mfdict, file, node) == -1)
107 goto bail;
107 goto bail;
108
108
109 start = cur + 1;
109 start = cur + 1;
110 zero = NULL;
110 zero = NULL;
111
111
112 Py_XDECREF(flags);
112 Py_XDECREF(flags);
113 Py_XDECREF(node);
113 Py_XDECREF(node);
114 Py_XDECREF(file);
114 Py_XDECREF(file);
115 continue;
115 continue;
116 bail:
116 bail:
117 Py_XDECREF(flags);
117 Py_XDECREF(flags);
118 Py_XDECREF(node);
118 Py_XDECREF(node);
119 Py_XDECREF(file);
119 Py_XDECREF(file);
120 goto quit;
120 goto quit;
121 }
121 }
122
122
123 if (len > 0 && *(cur - 1) != '\n') {
123 if (len > 0 && *(cur - 1) != '\n') {
124 PyErr_SetString(PyExc_ValueError,
124 PyErr_SetString(PyExc_ValueError,
125 "manifest contains trailing garbage");
125 "manifest contains trailing garbage");
126 goto quit;
126 goto quit;
127 }
127 }
128
128
129 Py_INCREF(Py_None);
129 Py_INCREF(Py_None);
130 return Py_None;
130 return Py_None;
131 quit:
131 quit:
132 return NULL;
132 return NULL;
133 }
133 }
134
134
135 #ifdef _WIN32
135 #ifdef _WIN32
136 # ifdef _MSC_VER
136 # ifdef _MSC_VER
137 /* msvc 6.0 has problems */
137 /* msvc 6.0 has problems */
138 # define inline __inline
138 # define inline __inline
139 typedef unsigned long uint32_t;
139 typedef unsigned long uint32_t;
140 typedef unsigned __int64 uint64_t;
140 typedef unsigned __int64 uint64_t;
141 # else
141 # else
142 # include <stdint.h>
142 # include <stdint.h>
143 # endif
143 # endif
144 static uint32_t ntohl(uint32_t x)
144 static uint32_t ntohl(uint32_t x)
145 {
145 {
146 return ((x & 0x000000ffUL) << 24) |
146 return ((x & 0x000000ffUL) << 24) |
147 ((x & 0x0000ff00UL) << 8) |
147 ((x & 0x0000ff00UL) << 8) |
148 ((x & 0x00ff0000UL) >> 8) |
148 ((x & 0x00ff0000UL) >> 8) |
149 ((x & 0xff000000UL) >> 24);
149 ((x & 0xff000000UL) >> 24);
150 }
150 }
151 #else
151 #else
152 /* not windows */
152 /* not windows */
153 # include <sys/types.h>
153 # include <sys/types.h>
154 # if defined __BEOS__ && !defined __HAIKU__
154 # if defined __BEOS__ && !defined __HAIKU__
155 # include <ByteOrder.h>
155 # include <ByteOrder.h>
156 # else
156 # else
157 # include <arpa/inet.h>
157 # include <arpa/inet.h>
158 # endif
158 # endif
159 # include <inttypes.h>
159 # include <inttypes.h>
160 #endif
160 #endif
161
161
162 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
162 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
163 {
163 {
164 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
164 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
165 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
165 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
166 char *str, *cur, *end, *cpos;
166 char *str, *cur, *end, *cpos;
167 int state, mode, size, mtime, flen;
167 int state, mode, size, mtime;
168 unsigned int flen;
168 int len;
169 int len;
169 char decode[16]; /* for alignment */
170 char decode[16]; /* for alignment */
170
171
171 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
172 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
172 &PyDict_Type, &dmap,
173 &PyDict_Type, &dmap,
173 &PyDict_Type, &cmap,
174 &PyDict_Type, &cmap,
174 &str, &len))
175 &str, &len))
175 goto quit;
176 goto quit;
176
177
177 /* read parents */
178 /* read parents */
178 if (len < 40)
179 if (len < 40)
179 goto quit;
180 goto quit;
180
181
181 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
182 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
182 if (!parents)
183 if (!parents)
183 goto quit;
184 goto quit;
184
185
185 /* read filenames */
186 /* read filenames */
186 cur = str + 40;
187 cur = str + 40;
187 end = str + len;
188 end = str + len;
188
189
189 while (cur < end - 17) {
190 while (cur < end - 17) {
190 /* unpack header */
191 /* unpack header */
191 state = *cur;
192 state = *cur;
192 memcpy(decode, cur + 1, 16);
193 memcpy(decode, cur + 1, 16);
193 mode = ntohl(*(uint32_t *)(decode));
194 mode = ntohl(*(uint32_t *)(decode));
194 size = ntohl(*(uint32_t *)(decode + 4));
195 size = ntohl(*(uint32_t *)(decode + 4));
195 mtime = ntohl(*(uint32_t *)(decode + 8));
196 mtime = ntohl(*(uint32_t *)(decode + 8));
196 flen = ntohl(*(uint32_t *)(decode + 12));
197 flen = ntohl(*(uint32_t *)(decode + 12));
197 cur += 17;
198 cur += 17;
198 if (cur + flen > end)
199 if (flen > end - cur) {
200 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
199 goto quit;
201 goto quit;
202 }
200
203
201 entry = Py_BuildValue("ciii", state, mode, size, mtime);
204 entry = Py_BuildValue("ciii", state, mode, size, mtime);
202 PyObject_GC_UnTrack(entry); /* don't waste time with this */
205 PyObject_GC_UnTrack(entry); /* don't waste time with this */
203 if (!entry)
206 if (!entry)
204 goto quit;
207 goto quit;
205
208
206 cpos = memchr(cur, 0, flen);
209 cpos = memchr(cur, 0, flen);
207 if (cpos) {
210 if (cpos) {
208 fname = PyString_FromStringAndSize(cur, cpos - cur);
211 fname = PyString_FromStringAndSize(cur, cpos - cur);
209 cname = PyString_FromStringAndSize(cpos + 1,
212 cname = PyString_FromStringAndSize(cpos + 1,
210 flen - (cpos - cur) - 1);
213 flen - (cpos - cur) - 1);
211 if (!fname || !cname ||
214 if (!fname || !cname ||
212 PyDict_SetItem(cmap, fname, cname) == -1 ||
215 PyDict_SetItem(cmap, fname, cname) == -1 ||
213 PyDict_SetItem(dmap, fname, entry) == -1)
216 PyDict_SetItem(dmap, fname, entry) == -1)
214 goto quit;
217 goto quit;
215 Py_DECREF(cname);
218 Py_DECREF(cname);
216 } else {
219 } else {
217 fname = PyString_FromStringAndSize(cur, flen);
220 fname = PyString_FromStringAndSize(cur, flen);
218 if (!fname ||
221 if (!fname ||
219 PyDict_SetItem(dmap, fname, entry) == -1)
222 PyDict_SetItem(dmap, fname, entry) == -1)
220 goto quit;
223 goto quit;
221 }
224 }
222 cur += flen;
225 cur += flen;
223 Py_DECREF(fname);
226 Py_DECREF(fname);
224 Py_DECREF(entry);
227 Py_DECREF(entry);
225 fname = cname = entry = NULL;
228 fname = cname = entry = NULL;
226 }
229 }
227
230
228 ret = parents;
231 ret = parents;
229 Py_INCREF(ret);
232 Py_INCREF(ret);
230 quit:
233 quit:
231 Py_XDECREF(fname);
234 Py_XDECREF(fname);
232 Py_XDECREF(cname);
235 Py_XDECREF(cname);
233 Py_XDECREF(entry);
236 Py_XDECREF(entry);
234 Py_XDECREF(parents);
237 Py_XDECREF(parents);
235 return ret;
238 return ret;
236 }
239 }
237
240
238 const char nullid[20];
241 const char nullid[20];
239 const int nullrev = -1;
242 const int nullrev = -1;
240
243
241 /* create an index tuple, insert into the nodemap */
244 /* create an index tuple, insert into the nodemap */
242 static PyObject * _build_idx_entry(PyObject *nodemap, int n, uint64_t offset_flags,
245 static PyObject * _build_idx_entry(PyObject *nodemap, int n, uint64_t offset_flags,
243 int comp_len, int uncomp_len, int base_rev,
246 int comp_len, int uncomp_len, int base_rev,
244 int link_rev, int parent_1, int parent_2,
247 int link_rev, int parent_1, int parent_2,
245 const char *c_node_id)
248 const char *c_node_id)
246 {
249 {
247 int err;
250 int err;
248 PyObject *entry, *node_id, *n_obj;
251 PyObject *entry, *node_id, *n_obj;
249
252
250 node_id = PyString_FromStringAndSize(c_node_id, 20);
253 node_id = PyString_FromStringAndSize(c_node_id, 20);
251 n_obj = PyInt_FromLong(n);
254 n_obj = PyInt_FromLong(n);
252 if (!node_id || !n_obj)
255 if (!node_id || !n_obj)
253 err = -1;
256 err = -1;
254 else
257 else
255 err = PyDict_SetItem(nodemap, node_id, n_obj);
258 err = PyDict_SetItem(nodemap, node_id, n_obj);
256
259
257 Py_XDECREF(n_obj);
260 Py_XDECREF(n_obj);
258 if (err)
261 if (err)
259 goto error_dealloc;
262 goto error_dealloc;
260
263
261 entry = Py_BuildValue("LiiiiiiN", offset_flags, comp_len,
264 entry = Py_BuildValue("LiiiiiiN", offset_flags, comp_len,
262 uncomp_len, base_rev, link_rev,
265 uncomp_len, base_rev, link_rev,
263 parent_1, parent_2, node_id);
266 parent_1, parent_2, node_id);
264 if (!entry)
267 if (!entry)
265 goto error_dealloc;
268 goto error_dealloc;
266 PyObject_GC_UnTrack(entry); /* don't waste time with this */
269 PyObject_GC_UnTrack(entry); /* don't waste time with this */
267
270
268 return entry;
271 return entry;
269
272
270 error_dealloc:
273 error_dealloc:
271 Py_XDECREF(node_id);
274 Py_XDECREF(node_id);
272 return NULL;
275 return NULL;
273 }
276 }
274
277
275 /* RevlogNG format (all in big endian, data may be inlined):
278 /* RevlogNG format (all in big endian, data may be inlined):
276 * 6 bytes: offset
279 * 6 bytes: offset
277 * 2 bytes: flags
280 * 2 bytes: flags
278 * 4 bytes: compressed length
281 * 4 bytes: compressed length
279 * 4 bytes: uncompressed length
282 * 4 bytes: uncompressed length
280 * 4 bytes: base revision
283 * 4 bytes: base revision
281 * 4 bytes: link revision
284 * 4 bytes: link revision
282 * 4 bytes: parent 1 revision
285 * 4 bytes: parent 1 revision
283 * 4 bytes: parent 2 revision
286 * 4 bytes: parent 2 revision
284 * 32 bytes: nodeid (only 20 bytes used)
287 * 32 bytes: nodeid (only 20 bytes used)
285 */
288 */
286 static int _parse_index_ng (const char *data, int size, int inlined,
289 static int _parse_index_ng (const char *data, int size, int inlined,
287 PyObject *index, PyObject *nodemap)
290 PyObject *index, PyObject *nodemap)
288 {
291 {
289 PyObject *entry;
292 PyObject *entry;
290 int n = 0, err;
293 int n = 0, err;
291 uint64_t offset_flags;
294 uint64_t offset_flags;
292 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
295 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
293 const char *c_node_id;
296 const char *c_node_id;
294 const char *end = data + size;
297 const char *end = data + size;
295
298
296 while (data < end) {
299 while (data < end) {
300 unsigned int step;
301
297 offset_flags = ntohl(*((uint32_t *) (data + 4)));
302 offset_flags = ntohl(*((uint32_t *) (data + 4)));
298 if (n == 0) /* mask out version number for the first entry */
303 if (n == 0) /* mask out version number for the first entry */
299 offset_flags &= 0xFFFF;
304 offset_flags &= 0xFFFF;
300 else {
305 else {
301 uint32_t offset_high = ntohl(*((uint32_t *) data));
306 uint32_t offset_high = ntohl(*((uint32_t *) data));
302 offset_flags |= ((uint64_t) offset_high) << 32;
307 offset_flags |= ((uint64_t) offset_high) << 32;
303 }
308 }
304
309
305 comp_len = ntohl(*((uint32_t *) (data + 8)));
310 comp_len = ntohl(*((uint32_t *) (data + 8)));
306 uncomp_len = ntohl(*((uint32_t *) (data + 12)));
311 uncomp_len = ntohl(*((uint32_t *) (data + 12)));
307 base_rev = ntohl(*((uint32_t *) (data + 16)));
312 base_rev = ntohl(*((uint32_t *) (data + 16)));
308 link_rev = ntohl(*((uint32_t *) (data + 20)));
313 link_rev = ntohl(*((uint32_t *) (data + 20)));
309 parent_1 = ntohl(*((uint32_t *) (data + 24)));
314 parent_1 = ntohl(*((uint32_t *) (data + 24)));
310 parent_2 = ntohl(*((uint32_t *) (data + 28)));
315 parent_2 = ntohl(*((uint32_t *) (data + 28)));
311 c_node_id = data + 32;
316 c_node_id = data + 32;
312
317
313 entry = _build_idx_entry(nodemap, n, offset_flags,
318 entry = _build_idx_entry(nodemap, n, offset_flags,
314 comp_len, uncomp_len, base_rev,
319 comp_len, uncomp_len, base_rev,
315 link_rev, parent_1, parent_2,
320 link_rev, parent_1, parent_2,
316 c_node_id);
321 c_node_id);
317 if (!entry)
322 if (!entry)
318 return 0;
323 return 0;
319
324
320 if (inlined) {
325 if (inlined) {
321 err = PyList_Append(index, entry);
326 err = PyList_Append(index, entry);
322 Py_DECREF(entry);
327 Py_DECREF(entry);
323 if (err)
328 if (err)
324 return 0;
329 return 0;
325 } else
330 } else
326 PyList_SET_ITEM(index, n, entry); /* steals reference */
331 PyList_SET_ITEM(index, n, entry); /* steals reference */
327
332
328 data += 64 + (inlined ? comp_len : 0);
329 n++;
333 n++;
334 step = 64 + (inlined ? comp_len : 0);
335 if (end - data < step)
336 break;
337 data += step;
330 }
338 }
331 if (data > end) {
339 if (data != end) {
332 if (!PyErr_Occurred())
340 if (!PyErr_Occurred())
333 PyErr_SetString(PyExc_ValueError, "corrupt index file");
341 PyErr_SetString(PyExc_ValueError, "corrupt index file");
334 return 0;
342 return 0;
335 }
343 }
336
344
337 /* create the nullid/nullrev entry in the nodemap and the
345 /* create the nullid/nullrev entry in the nodemap and the
338 * magic nullid entry in the index at [-1] */
346 * magic nullid entry in the index at [-1] */
339 entry = _build_idx_entry(nodemap,
347 entry = _build_idx_entry(nodemap,
340 nullrev, 0, 0, 0, -1, -1, -1, -1, nullid);
348 nullrev, 0, 0, 0, -1, -1, -1, -1, nullid);
341 if (!entry)
349 if (!entry)
342 return 0;
350 return 0;
343 if (inlined) {
351 if (inlined) {
344 err = PyList_Append(index, entry);
352 err = PyList_Append(index, entry);
345 Py_DECREF(entry);
353 Py_DECREF(entry);
346 if (err)
354 if (err)
347 return 0;
355 return 0;
348 } else
356 } else
349 PyList_SET_ITEM(index, n, entry); /* steals reference */
357 PyList_SET_ITEM(index, n, entry); /* steals reference */
350
358
351 return 1;
359 return 1;
352 }
360 }
353
361
354 /* This function parses a index file and returns a Python tuple of the
362 /* This function parses a index file and returns a Python tuple of the
355 * following format: (index, nodemap, cache)
363 * following format: (index, nodemap, cache)
356 *
364 *
357 * index: a list of tuples containing the RevlogNG records
365 * index: a list of tuples containing the RevlogNG records
358 * nodemap: a dict mapping node ids to indices in the index list
366 * nodemap: a dict mapping node ids to indices in the index list
359 * cache: if data is inlined, a tuple (index_file_content, 0) else None
367 * cache: if data is inlined, a tuple (index_file_content, 0) else None
360 */
368 */
361 static PyObject *parse_index(PyObject *self, PyObject *args)
369 static PyObject *parse_index(PyObject *self, PyObject *args)
362 {
370 {
363 const char *data;
371 const char *data;
364 int size, inlined;
372 int size, inlined;
365 PyObject *rval = NULL, *index = NULL, *nodemap = NULL, *cache = NULL;
373 PyObject *rval = NULL, *index = NULL, *nodemap = NULL, *cache = NULL;
366 PyObject *data_obj = NULL, *inlined_obj;
374 PyObject *data_obj = NULL, *inlined_obj;
367
375
368 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
376 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
369 return NULL;
377 return NULL;
370 inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
378 inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
371
379
372 /* If no data is inlined, we know the size of the index list in
380 /* If no data is inlined, we know the size of the index list in
373 * advance: size divided by size of one one revlog record (64 bytes)
381 * advance: size divided by size of one one revlog record (64 bytes)
374 * plus one for the nullid */
382 * plus one for the nullid */
375 index = inlined ? PyList_New(0) : PyList_New(size / 64 + 1);
383 index = inlined ? PyList_New(0) : PyList_New(size / 64 + 1);
376 if (!index)
384 if (!index)
377 goto quit;
385 goto quit;
378
386
379 nodemap = PyDict_New();
387 nodemap = PyDict_New();
380 if (!nodemap)
388 if (!nodemap)
381 goto quit;
389 goto quit;
382
390
383 /* set up the cache return value */
391 /* set up the cache return value */
384 if (inlined) {
392 if (inlined) {
385 /* Note that the reference to data_obj is only borrowed */
393 /* Note that the reference to data_obj is only borrowed */
386 data_obj = PyTuple_GET_ITEM(args, 0);
394 data_obj = PyTuple_GET_ITEM(args, 0);
387 cache = Py_BuildValue("iO", 0, data_obj);
395 cache = Py_BuildValue("iO", 0, data_obj);
388 if (!cache)
396 if (!cache)
389 goto quit;
397 goto quit;
390 } else {
398 } else {
391 cache = Py_None;
399 cache = Py_None;
392 Py_INCREF(Py_None);
400 Py_INCREF(Py_None);
393 }
401 }
394
402
395 /* actually populate the index and the nodemap with data */
403 /* actually populate the index and the nodemap with data */
396 if (!_parse_index_ng (data, size, inlined, index, nodemap))
404 if (!_parse_index_ng (data, size, inlined, index, nodemap))
397 goto quit;
405 goto quit;
398
406
399 rval = Py_BuildValue("NNN", index, nodemap, cache);
407 rval = Py_BuildValue("NNN", index, nodemap, cache);
400 if (!rval)
408 if (!rval)
401 goto quit;
409 goto quit;
402 return rval;
410 return rval;
403
411
404 quit:
412 quit:
405 Py_XDECREF(index);
413 Py_XDECREF(index);
406 Py_XDECREF(nodemap);
414 Py_XDECREF(nodemap);
407 Py_XDECREF(cache);
415 Py_XDECREF(cache);
408 Py_XDECREF(rval);
416 Py_XDECREF(rval);
409 return NULL;
417 return NULL;
410 }
418 }
411
419
412
420
413 static char parsers_doc[] = "Efficient content parsing.";
421 static char parsers_doc[] = "Efficient content parsing.";
414
422
415 static PyMethodDef methods[] = {
423 static PyMethodDef methods[] = {
416 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
424 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
417 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
425 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
418 {"parse_index", parse_index, METH_VARARGS, "parse a revlog index\n"},
426 {"parse_index", parse_index, METH_VARARGS, "parse a revlog index\n"},
419 {NULL, NULL}
427 {NULL, NULL}
420 };
428 };
421
429
422 PyMODINIT_FUNC initparsers(void)
430 PyMODINIT_FUNC initparsers(void)
423 {
431 {
424 Py_InitModule3("parsers", methods, parsers_doc);
432 Py_InitModule3("parsers", methods, parsers_doc);
425 }
433 }
General Comments 0
You need to be logged in to leave comments. Login now