diff options
Diffstat (limited to 'src/plugins/deb_extractor.c')
-rw-r--r-- | src/plugins/deb_extractor.c | 284 |
1 files changed, 143 insertions, 141 deletions
diff --git a/src/plugins/deb_extractor.c b/src/plugins/deb_extractor.c index 2eb0028..16c6285 100644 --- a/src/plugins/deb_extractor.c +++ b/src/plugins/deb_extractor.c | |||
@@ -122,8 +122,8 @@ static struct Matches tmap[] = { | |||
122 | static int | 122 | static int |
123 | processControl (const char *data, | 123 | processControl (const char *data, |
124 | const size_t size, | 124 | const size_t size, |
125 | EXTRACTOR_MetaDataProcessor proc, | 125 | EXTRACTOR_MetaDataProcessor proc, |
126 | void *proc_cls) | 126 | void *proc_cls) |
127 | { | 127 | { |
128 | size_t pos; | 128 | size_t pos; |
129 | char *key; | 129 | char *key; |
@@ -134,49 +134,49 @@ processControl (const char *data, | |||
134 | 134 | ||
135 | pos = 0; | 135 | pos = 0; |
136 | while (pos < size) | 136 | while (pos < size) |
137 | { | 137 | { |
138 | for (colon = pos; ':' != data[colon]; colon++) | 138 | for (colon = pos; ':' != data[colon]; colon++) |
139 | if ((colon > size) || ('\n' == data[colon])) | 139 | if ((colon > size) || ('\n' == data[colon])) |
140 | return 0; | 140 | return 0; |
141 | colon++; | ||
142 | while ((colon < size) && (isspace ((unsigned char) data[colon]))) | ||
141 | colon++; | 143 | colon++; |
142 | while ((colon < size) && (isspace ((unsigned char) data[colon]))) | 144 | eol = colon; |
143 | colon++; | 145 | while ((eol < size) && |
144 | eol = colon; | 146 | (('\n' != data[eol]) || |
145 | while ((eol < size) && | 147 | ((eol + 1 < size) && (' ' == data[eol + 1])))) |
146 | (('\n' != data[eol]) || | 148 | eol++; |
147 | ((eol + 1 < size) && (' ' == data[eol + 1])))) | 149 | if ((eol == colon) || (eol > size)) |
148 | eol++; | 150 | return 0; |
149 | if ((eol == colon) || (eol > size)) | 151 | if (NULL == (key = stndup (&data[pos], colon - pos))) |
152 | return 0; | ||
153 | for (i = 0; NULL != tmap[i].text; i++) | ||
154 | { | ||
155 | if (0 != strcmp (key, tmap[i].text)) | ||
156 | continue; | ||
157 | if (NULL == (val = stndup (&data[colon], eol - colon))) | ||
158 | { | ||
159 | free (key); | ||
150 | return 0; | 160 | return 0; |
151 | if (NULL == (key = stndup (&data[pos], colon - pos))) | 161 | } |
152 | return 0; | 162 | if (0 != proc (proc_cls, |
153 | for (i = 0; NULL != tmap[i].text; i++) | 163 | "deb", |
154 | { | 164 | tmap[i].type, |
155 | if (0 != strcmp (key, tmap[i].text)) | 165 | EXTRACTOR_METAFORMAT_UTF8, |
156 | continue; | 166 | "text/plain", |
157 | if (NULL == (val = stndup (&data[colon], eol - colon))) | 167 | val, |
158 | { | 168 | strlen (val) + 1)) |
159 | free (key); | 169 | { |
160 | return 0; | 170 | free (val); |
161 | } | 171 | free (key); |
162 | if (0 != proc (proc_cls, | 172 | return 1; |
163 | "deb", | 173 | } |
164 | tmap[i].type, | 174 | free (val); |
165 | EXTRACTOR_METAFORMAT_UTF8, | 175 | break; |
166 | "text/plain", | ||
167 | val, | ||
168 | strlen(val) + 1)) | ||
169 | { | ||
170 | free (val); | ||
171 | free (key); | ||
172 | return 1; | ||
173 | } | ||
174 | free (val); | ||
175 | break; | ||
176 | } | ||
177 | free (key); | ||
178 | pos = eol + 1; | ||
179 | } | 176 | } |
177 | free (key); | ||
178 | pos = eol + 1; | ||
179 | } | ||
180 | return 0; | 180 | return 0; |
181 | } | 181 | } |
182 | 182 | ||
@@ -291,9 +291,9 @@ struct USTarHeader | |||
291 | */ | 291 | */ |
292 | static int | 292 | static int |
293 | processControlTar (const char *data, | 293 | processControlTar (const char *data, |
294 | size_t size, | 294 | size_t size, |
295 | EXTRACTOR_MetaDataProcessor proc, | 295 | EXTRACTOR_MetaDataProcessor proc, |
296 | void *proc_cls) | 296 | void *proc_cls) |
297 | { | 297 | { |
298 | struct TarHeader *tar; | 298 | struct TarHeader *tar; |
299 | struct USTarHeader *ustar; | 299 | struct USTarHeader *ustar; |
@@ -301,42 +301,42 @@ processControlTar (const char *data, | |||
301 | 301 | ||
302 | pos = 0; | 302 | pos = 0; |
303 | while (pos + sizeof (struct TarHeader) < size) | 303 | while (pos + sizeof (struct TarHeader) < size) |
304 | { | ||
305 | unsigned long long fsize; | ||
306 | char buf[13]; | ||
307 | |||
308 | tar = (struct TarHeader *) &data[pos]; | ||
309 | if (pos + sizeof (struct USTarHeader) < size) | ||
304 | { | 310 | { |
305 | unsigned long long fsize; | 311 | ustar = (struct USTarHeader *) &data[pos]; |
306 | char buf[13]; | 312 | if (0 == strncmp ("ustar", &ustar->magic[0], strlen ("ustar"))) |
307 | 313 | pos += 512; /* sizeof (struct USTarHeader); */ | |
308 | tar = (struct TarHeader *) & data[pos]; | ||
309 | if (pos + sizeof (struct USTarHeader) < size) | ||
310 | { | ||
311 | ustar = (struct USTarHeader *) & data[pos]; | ||
312 | if (0 == strncmp ("ustar", &ustar->magic[0], strlen ("ustar"))) | ||
313 | pos += 512; /* sizeof (struct USTarHeader); */ | ||
314 | else | ||
315 | pos += 257; /* sizeof (struct TarHeader); minus gcc alignment... */ | ||
316 | } | ||
317 | else | 314 | else |
318 | { | 315 | pos += 257; /* sizeof (struct TarHeader); minus gcc alignment... */ |
319 | pos += 257; /* sizeof (struct TarHeader); minus gcc alignment... */ | 316 | } |
320 | } | 317 | else |
318 | { | ||
319 | pos += 257; /* sizeof (struct TarHeader); minus gcc alignment... */ | ||
320 | } | ||
321 | 321 | ||
322 | memcpy (buf, &tar->filesize[0], 12); | 322 | memcpy (buf, &tar->filesize[0], 12); |
323 | buf[12] = '\0'; | 323 | buf[12] = '\0'; |
324 | if (1 != sscanf (buf, "%12llo", &fsize)) /* octal! Yuck yuck! */ | 324 | if (1 != sscanf (buf, "%12llo", &fsize)) /* octal! Yuck yuck! */ |
325 | return 0; | 325 | return 0; |
326 | if ((pos + fsize > size) || (fsize > size) || (pos + fsize < pos)) | 326 | if ((pos + fsize > size) || (fsize > size) || (pos + fsize < pos)) |
327 | return 0; | 327 | return 0; |
328 | 328 | ||
329 | if (0 == strncmp (&tar->name[0], "./control", strlen ("./control"))) | 329 | if (0 == strncmp (&tar->name[0], "./control", strlen ("./control"))) |
330 | { | 330 | { |
331 | /* found the 'control' file we were looking for */ | 331 | /* found the 'control' file we were looking for */ |
332 | return processControl (&data[pos], fsize, proc, proc_cls); | 332 | return processControl (&data[pos], fsize, proc, proc_cls); |
333 | } | ||
334 | if (0 != (fsize & 511)) | ||
335 | fsize = (fsize | 511) + 1; /* round up! */ | ||
336 | if (pos + fsize < pos) | ||
337 | return 0; | ||
338 | pos += fsize; | ||
339 | } | 333 | } |
334 | if (0 != (fsize & 511)) | ||
335 | fsize = (fsize | 511) + 1; /* round up! */ | ||
336 | if (pos + fsize < pos) | ||
337 | return 0; | ||
338 | pos += fsize; | ||
339 | } | ||
340 | return 0; | 340 | return 0; |
341 | } | 341 | } |
342 | 342 | ||
@@ -371,42 +371,43 @@ processControlTGZ (struct EXTRACTOR_ExtractContext *ec, | |||
371 | return 0; | 371 | return 0; |
372 | off = 0; | 372 | off = 0; |
373 | while (off < size) | 373 | while (off < size) |
374 | { | 374 | { |
375 | if (0 >= (sret = ec->read (ec->cls, &data, size - off))) | 375 | if (0 >= (sret = ec->read (ec->cls, &data, size - off))) |
376 | { | ||
377 | free (cdata); | ||
378 | return 0; | ||
379 | } | ||
380 | memcpy (&cdata[off], | ||
381 | data, | ||
382 | sret); | ||
383 | off += sret; | ||
384 | } | ||
385 | bufSize = cdata[size - 4] + (cdata[size - 3] << 8) + (cdata[size - 2] << 16) + (cdata[size - 1] << 24); | ||
386 | if (bufSize > MAX_CONTROL_SIZE) | ||
387 | { | 376 | { |
388 | free (cdata); | 377 | free (cdata); |
389 | return 0; | 378 | return 0; |
390 | } | 379 | } |
380 | memcpy (&cdata[off], | ||
381 | data, | ||
382 | sret); | ||
383 | off += sret; | ||
384 | } | ||
385 | bufSize = cdata[size - 4] + (cdata[size - 3] << 8) + (cdata[size - 2] << 16) | ||
386 | + (cdata[size - 1] << 24); | ||
387 | if (bufSize > MAX_CONTROL_SIZE) | ||
388 | { | ||
389 | free (cdata); | ||
390 | return 0; | ||
391 | } | ||
391 | if (NULL == (buf = malloc (bufSize))) | 392 | if (NULL == (buf = malloc (bufSize))) |
392 | { | 393 | { |
393 | free (cdata); | 394 | free (cdata); |
394 | return 0; | 395 | return 0; |
395 | } | 396 | } |
396 | ret = 0; | 397 | ret = 0; |
397 | memset (&strm, 0, sizeof (z_stream)); | 398 | memset (&strm, 0, sizeof (z_stream)); |
398 | strm.next_in = (Bytef *) data; | 399 | strm.next_in = (Bytef *) data; |
399 | strm.avail_in = size; | 400 | strm.avail_in = size; |
400 | if (Z_OK == inflateInit2 (&strm, 15 + 32)) | 401 | if (Z_OK == inflateInit2 (&strm, 15 + 32)) |
401 | { | 402 | { |
402 | strm.next_out = (Bytef *) buf; | 403 | strm.next_out = (Bytef *) buf; |
403 | strm.avail_out = bufSize; | 404 | strm.avail_out = bufSize; |
404 | inflate (&strm, Z_FINISH); | 405 | inflate (&strm, Z_FINISH); |
405 | if (strm.total_out > 0) | 406 | if (strm.total_out > 0) |
406 | ret = processControlTar (buf, strm.total_out, | 407 | ret = processControlTar (buf, strm.total_out, |
407 | ec->proc, ec->cls); | 408 | ec->proc, ec->cls); |
408 | inflateEnd (&strm); | 409 | inflateEnd (&strm); |
409 | } | 410 | } |
410 | free (buf); | 411 | free (buf); |
411 | free (cdata); | 412 | free (cdata); |
412 | return ret; | 413 | return ret; |
@@ -481,49 +482,50 @@ EXTRACTOR_deb_extract_method (struct EXTRACTOR_ExtractContext *ec) | |||
481 | return; | 482 | return; |
482 | pos = 8; | 483 | pos = 8; |
483 | while (pos + sizeof (struct ObjectHeader) < fsize) | 484 | while (pos + sizeof (struct ObjectHeader) < fsize) |
485 | { | ||
486 | if (pos != | ||
487 | ec->seek (ec->cls, pos, SEEK_SET)) | ||
488 | return; | ||
489 | if (sizeof (struct ObjectHeader) != | ||
490 | ec->read (ec->cls, &data, sizeof (struct ObjectHeader))) | ||
491 | return; | ||
492 | hdr = data; | ||
493 | if (0 != strncmp (&hdr->trailer[0], "`\n", 2)) | ||
494 | return; | ||
495 | memcpy (buf, &hdr->filesize[0], 10); | ||
496 | buf[10] = '\0'; | ||
497 | if (1 != sscanf (buf, "%10llu", &csize)) | ||
498 | return; | ||
499 | pos += sizeof (struct ObjectHeader); | ||
500 | if ((pos + csize > fsize) || (csize > fsize) || (pos + csize < pos)) | ||
501 | return; | ||
502 | if (0 == strncmp (&hdr->name[0], | ||
503 | "control.tar.gz", | ||
504 | strlen ("control.tar.gz"))) | ||
484 | { | 505 | { |
485 | if (pos != | 506 | if (0 != processControlTGZ (ec, |
486 | ec->seek (ec->cls, pos, SEEK_SET)) | 507 | csize)) |
487 | return; | ||
488 | if (sizeof (struct ObjectHeader) != | ||
489 | ec->read (ec->cls, &data, sizeof (struct ObjectHeader))) | ||
490 | return; | ||
491 | hdr = data; | ||
492 | if (0 != strncmp (&hdr->trailer[0], "`\n", 2)) | ||
493 | return; | 508 | return; |
494 | memcpy (buf, &hdr->filesize[0], 10); | 509 | done++; |
495 | buf[10] = '\0'; | 510 | } |
496 | if (1 != sscanf (buf, "%10llu", &csize)) | 511 | if (0 == strncmp (&hdr->name[0], |
497 | return; | 512 | "debian-binary", strlen ("debian-binary"))) |
498 | pos += sizeof (struct ObjectHeader); | 513 | { |
499 | if ((pos + csize > fsize) || (csize > fsize) || (pos + csize < pos)) | 514 | if (0 != ec->proc (ec->cls, |
515 | "deb", | ||
516 | EXTRACTOR_METATYPE_MIMETYPE, | ||
517 | EXTRACTOR_METAFORMAT_UTF8, | ||
518 | "text/plain", | ||
519 | "application/x-debian-package", | ||
520 | strlen ("application/x-debian-package") + 1)) | ||
500 | return; | 521 | return; |
501 | if (0 == strncmp (&hdr->name[0], | 522 | done++; |
502 | "control.tar.gz", | ||
503 | strlen ("control.tar.gz"))) | ||
504 | { | ||
505 | if (0 != processControlTGZ (ec, | ||
506 | csize)) | ||
507 | return; | ||
508 | done++; | ||
509 | } | ||
510 | if (0 == strncmp (&hdr->name[0], | ||
511 | "debian-binary", strlen ("debian-binary"))) | ||
512 | { | ||
513 | if (0 != ec->proc (ec->cls, | ||
514 | "deb", | ||
515 | EXTRACTOR_METATYPE_MIMETYPE, | ||
516 | EXTRACTOR_METAFORMAT_UTF8, | ||
517 | "text/plain", | ||
518 | "application/x-debian-package", | ||
519 | strlen ("application/x-debian-package")+1)) | ||
520 | return; | ||
521 | done++; | ||
522 | } | ||
523 | pos += csize; | ||
524 | if (2 == done) | ||
525 | break; /* no need to process the rest of the archive */ | ||
526 | } | 523 | } |
524 | pos += csize; | ||
525 | if (2 == done) | ||
526 | break; /* no need to process the rest of the archive */ | ||
527 | } | ||
527 | } | 528 | } |
528 | 529 | ||
530 | |||
529 | /* end of deb_extractor.c */ | 531 | /* end of deb_extractor.c */ |