1/*- 2 * Copyright (c) 2003-2007 Tim Kientzle 3 * Copyright (c) 2012 Michihiro NAKAJIMA 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "archive_platform.h" 28 29#ifdef HAVE_UNISTD_H 30#include <unistd.h> 31#endif 32#ifdef HAVE_ERRNO_H 33#include <errno.h> 34#endif 35#ifdef HAVE_STDLIB_H 36#include <stdlib.h> 37#endif 38#ifdef HAVE_STRING_H 39#include <string.h> 40#endif 41#ifdef HAVE_UNISTD_H 42#include <unistd.h> 43#endif 44#ifdef HAVE_LZO_LZOCONF_H 45#include <lzo/lzoconf.h> 46#endif 47#ifdef HAVE_LZO_LZO1X_H 48#include <lzo/lzo1x.h> 49#endif 50#ifdef HAVE_ZLIB_H 51#include <zlib.h> /* for crc32 and adler32 */ 52#endif 53 54#include "archive.h" 55#if !defined(HAVE_ZLIB_H) &&\ 56 defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) 57#include "archive_crc32.h" 58#endif 59#include "archive_endian.h" 60#include "archive_private.h" 61#include "archive_read_private.h" 62 63#ifndef HAVE_ZLIB_H 64#define adler32 lzo_adler32 65#endif 66 67#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" 68#define LZOP_HEADER_MAGIC_LEN 9 69 70#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) 71struct read_lzop { 72 unsigned char *out_block; 73 size_t out_block_size; 74 int64_t total_out; 75 int flags; 76 uint32_t compressed_cksum; 77 uint32_t uncompressed_cksum; 78 size_t compressed_size; 79 size_t uncompressed_size; 80 size_t unconsumed_bytes; 81 char in_stream; 82 char eof; /* True = found end of compressed data. */ 83}; 84 85#define FILTER 0x0800 86#define CRC32_HEADER 0x1000 87#define EXTRA_FIELD 0x0040 88#define ADLER32_UNCOMPRESSED 0x0001 89#define ADLER32_COMPRESSED 0x0002 90#define CRC32_UNCOMPRESSED 0x0100 91#define CRC32_COMPRESSED 0x0200 92#define MAX_BLOCK_SIZE (64 * 1024 * 1024) 93 94static ssize_t lzop_filter_read(struct archive_read_filter *, const void **); 95static int lzop_filter_close(struct archive_read_filter *); 96#endif 97 98static int lzop_bidder_bid(struct archive_read_filter_bidder *, 99 struct archive_read_filter *); 100static int lzop_bidder_init(struct archive_read_filter *); 101 102static const struct archive_read_filter_bidder_vtable 103lzop_bidder_vtable = { 104 .bid = lzop_bidder_bid, 105 .init = lzop_bidder_init, 106}; 107 108int 109archive_read_support_filter_lzop(struct archive *_a) 110{ 111 struct archive_read *a = (struct archive_read *)_a; 112 113 if (__archive_read_register_bidder(a, NULL, NULL, 114 &lzop_bidder_vtable) != ARCHIVE_OK) 115 return (ARCHIVE_FATAL); 116 117 /* Signal the extent of lzop support with the return value here. */ 118#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) 119 return (ARCHIVE_OK); 120#else 121 /* Return ARCHIVE_WARN since this always uses an external program. */ 122 archive_set_error(_a, ARCHIVE_ERRNO_MISC, 123 "Using external lzop program for lzop decompression"); 124 return (ARCHIVE_WARN); 125#endif 126} 127 128/* 129 * Bidder just verifies the header and returns the number of verified bits. 130 */ 131static int 132lzop_bidder_bid(struct archive_read_filter_bidder *self, 133 struct archive_read_filter *filter) 134{ 135 const unsigned char *p; 136 ssize_t avail; 137 138 (void)self; /* UNUSED */ 139 140 p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail); 141 if (p == NULL || avail == 0) 142 return (0); 143 144 if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) 145 return (0); 146 147 return (LZOP_HEADER_MAGIC_LEN * 8); 148} 149 150#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H) 151/* 152 * If we don't have the library on this system, we can't do the 153 * decompression directly. We can, however, try to run "lzop -d" 154 * in case that's available. 155 */ 156static int 157lzop_bidder_init(struct archive_read_filter *self) 158{ 159 int r; 160 161 r = __archive_read_program(self, "lzop -d"); 162 /* Note: We set the format here even if __archive_read_program() 163 * above fails. We do, after all, know what the format is 164 * even if we weren't able to read it. */ 165 self->code = ARCHIVE_FILTER_LZOP; 166 self->name = "lzop"; 167 return (r); 168} 169#else 170 171static const struct archive_read_filter_vtable 172lzop_reader_vtable = { 173 .read = lzop_filter_read, 174 .close = lzop_filter_close 175}; 176 177/* 178 * Initialize the filter object. 179 */ 180static int 181lzop_bidder_init(struct archive_read_filter *self) 182{ 183 struct read_lzop *state; 184 185 self->code = ARCHIVE_FILTER_LZOP; 186 self->name = "lzop"; 187 188 state = (struct read_lzop *)calloc(1, sizeof(*state)); 189 if (state == NULL) { 190 archive_set_error(&self->archive->archive, ENOMEM, 191 "Can't allocate data for lzop decompression"); 192 return (ARCHIVE_FATAL); 193 } 194 195 self->data = state; 196 self->vtable = &lzop_reader_vtable; 197 198 return (ARCHIVE_OK); 199} 200 201static int 202consume_header(struct archive_read_filter *self) 203{ 204 struct read_lzop *state = (struct read_lzop *)self->data; 205 const unsigned char *p, *_p; 206 unsigned checksum, flags, len, method, version; 207 208 /* 209 * Check LZOP magic code. 210 */ 211 p = __archive_read_filter_ahead(self->upstream, 212 LZOP_HEADER_MAGIC_LEN, NULL); 213 if (p == NULL) 214 return (ARCHIVE_EOF); 215 216 if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) 217 return (ARCHIVE_EOF); 218 __archive_read_filter_consume(self->upstream, 219 LZOP_HEADER_MAGIC_LEN); 220 221 p = __archive_read_filter_ahead(self->upstream, 29, NULL); 222 if (p == NULL) 223 goto truncated; 224 _p = p; 225 version = archive_be16dec(p); 226 p += 4;/* version(2 bytes) + library version(2 bytes) */ 227 228 if (version >= 0x940) { 229 unsigned reqversion = archive_be16dec(p); p += 2; 230 if (reqversion < 0x900) { 231 archive_set_error(&self->archive->archive, 232 ARCHIVE_ERRNO_MISC, "Invalid required version"); 233 return (ARCHIVE_FAILED); 234 } 235 } 236 237 method = *p++; 238 if (method < 1 || method > 3) { 239 archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 240 "Unsupported method"); 241 return (ARCHIVE_FAILED); 242 } 243 244 if (version >= 0x940) { 245 unsigned level = *p++; 246#if 0 247 unsigned default_level[] = {0, 3, 1, 9}; 248#endif 249 if (level == 0) 250 /* Method is 1..3 here due to check above. */ 251#if 0 /* Avoid an error Clang Static Analyzer claims 252 "Value stored to 'level' is never read". */ 253 level = default_level[method]; 254#else 255 ;/* NOP */ 256#endif 257 else if (level > 9) { 258 archive_set_error(&self->archive->archive, 259 ARCHIVE_ERRNO_MISC, "Invalid level"); 260 return (ARCHIVE_FAILED); 261 } 262 } 263 264 flags = archive_be32dec(p); p += 4; 265 266 if (flags & FILTER) 267 p += 4; /* Skip filter */ 268 p += 4; /* Skip mode */ 269 if (version >= 0x940) 270 p += 8; /* Skip mtime */ 271 else 272 p += 4; /* Skip mtime */ 273 len = *p++; /* Read filename length */ 274 len += p - _p; 275 /* Make sure we have all bytes we need to calculate checksum. */ 276 p = __archive_read_filter_ahead(self->upstream, len + 4, NULL); 277 if (p == NULL) 278 goto truncated; 279 if (flags & CRC32_HEADER) 280 checksum = crc32(crc32(0, NULL, 0), p, len); 281 else 282 checksum = adler32(adler32(0, NULL, 0), p, len); 283#ifndef DONT_FAIL_ON_CRC_ERROR 284 if (archive_be32dec(p + len) != checksum) 285 goto corrupted; 286#endif 287 __archive_read_filter_consume(self->upstream, len + 4); 288 if (flags & EXTRA_FIELD) { 289 /* Skip extra field */ 290 p = __archive_read_filter_ahead(self->upstream, 4, NULL); 291 if (p == NULL) 292 goto truncated; 293 len = archive_be32dec(p); 294 __archive_read_filter_consume(self->upstream, len + 4 + 4); 295 } 296 state->flags = flags; 297 state->in_stream = 1; 298 return (ARCHIVE_OK); 299truncated: 300 archive_set_error(&self->archive->archive, 301 ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); 302 return (ARCHIVE_FAILED); 303corrupted: 304 archive_set_error(&self->archive->archive, 305 ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); 306 return (ARCHIVE_FAILED); 307} 308 309static int 310consume_block_info(struct archive_read_filter *self) 311{ 312 struct read_lzop *state = (struct read_lzop *)self->data; 313 const unsigned char *p; 314 unsigned flags = state->flags; 315 316 p = __archive_read_filter_ahead(self->upstream, 4, NULL); 317 if (p == NULL) 318 goto truncated; 319 state->uncompressed_size = archive_be32dec(p); 320 __archive_read_filter_consume(self->upstream, 4); 321 if (state->uncompressed_size == 0) 322 return (ARCHIVE_EOF); 323 if (state->uncompressed_size > MAX_BLOCK_SIZE) 324 goto corrupted; 325 326 p = __archive_read_filter_ahead(self->upstream, 4, NULL); 327 if (p == NULL) 328 goto truncated; 329 state->compressed_size = archive_be32dec(p); 330 __archive_read_filter_consume(self->upstream, 4); 331 if (state->compressed_size > state->uncompressed_size) 332 goto corrupted; 333 334 if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) { 335 p = __archive_read_filter_ahead(self->upstream, 4, NULL); 336 if (p == NULL) 337 goto truncated; 338 state->compressed_cksum = state->uncompressed_cksum = 339 archive_be32dec(p); 340 __archive_read_filter_consume(self->upstream, 4); 341 } 342 if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) && 343 state->compressed_size < state->uncompressed_size) { 344 p = __archive_read_filter_ahead(self->upstream, 4, NULL); 345 if (p == NULL) 346 goto truncated; 347 state->compressed_cksum = archive_be32dec(p); 348 __archive_read_filter_consume(self->upstream, 4); 349 } 350 return (ARCHIVE_OK); 351truncated: 352 archive_set_error(&self->archive->archive, 353 ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); 354 return (ARCHIVE_FAILED); 355corrupted: 356 archive_set_error(&self->archive->archive, 357 ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); 358 return (ARCHIVE_FAILED); 359} 360 361static ssize_t 362lzop_filter_read(struct archive_read_filter *self, const void **p) 363{ 364 struct read_lzop *state = (struct read_lzop *)self->data; 365 const void *b; 366 lzo_uint out_size; 367 uint32_t cksum; 368 int ret, r; 369 370 if (state->unconsumed_bytes) { 371 __archive_read_filter_consume(self->upstream, 372 state->unconsumed_bytes); 373 state->unconsumed_bytes = 0; 374 } 375 if (state->eof) 376 return (0); 377 378 for (;;) { 379 if (!state->in_stream) { 380 ret = consume_header(self); 381 if (ret < ARCHIVE_OK) 382 return (ret); 383 if (ret == ARCHIVE_EOF) { 384 state->eof = 1; 385 return (0); 386 } 387 } 388 ret = consume_block_info(self); 389 if (ret < ARCHIVE_OK) 390 return (ret); 391 if (ret == ARCHIVE_EOF) 392 state->in_stream = 0; 393 else 394 break; 395 } 396 397 if (state->out_block == NULL || 398 state->out_block_size < state->uncompressed_size) { 399 void *new_block; 400 401 new_block = realloc(state->out_block, state->uncompressed_size); 402 if (new_block == NULL) { 403 archive_set_error(&self->archive->archive, ENOMEM, 404 "Can't allocate data for lzop decompression"); 405 return (ARCHIVE_FATAL); 406 } 407 state->out_block = new_block; 408 state->out_block_size = state->uncompressed_size; 409 } 410 411 b = __archive_read_filter_ahead(self->upstream, 412 state->compressed_size, NULL); 413 if (b == NULL) { 414 archive_set_error(&self->archive->archive, 415 ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); 416 return (ARCHIVE_FATAL); 417 } 418 if (state->flags & CRC32_COMPRESSED) 419 cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size); 420 else if (state->flags & ADLER32_COMPRESSED) 421 cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size); 422 else 423 cksum = state->compressed_cksum; 424 if (cksum != state->compressed_cksum) { 425 archive_set_error(&self->archive->archive, 426 ARCHIVE_ERRNO_MISC, "Corrupted data"); 427 return (ARCHIVE_FATAL); 428 } 429 430 /* 431 * If the both uncompressed size and compressed size are the same, 432 * we do not decompress this block. 433 */ 434 if (state->uncompressed_size == state->compressed_size) { 435 *p = b; 436 state->total_out += state->compressed_size; 437 state->unconsumed_bytes = state->compressed_size; 438 return ((ssize_t)state->uncompressed_size); 439 } 440 441 /* 442 * Drive lzo uncompression. 443 */ 444 out_size = (lzo_uint)state->uncompressed_size; 445 r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, 446 state->out_block, &out_size, NULL); 447 switch (r) { 448 case LZO_E_OK: 449 if (out_size == state->uncompressed_size) 450 break; 451 archive_set_error(&self->archive->archive, 452 ARCHIVE_ERRNO_MISC, "Corrupted data"); 453 return (ARCHIVE_FATAL); 454 case LZO_E_OUT_OF_MEMORY: 455 archive_set_error(&self->archive->archive, ENOMEM, 456 "lzop decompression failed: out of memory"); 457 return (ARCHIVE_FATAL); 458 default: 459 archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 460 "lzop decompression failed: %d", r); 461 return (ARCHIVE_FATAL); 462 } 463 464 if (state->flags & CRC32_UNCOMPRESSED) 465 cksum = crc32(crc32(0, NULL, 0), state->out_block, 466 state->uncompressed_size); 467 else if (state->flags & ADLER32_UNCOMPRESSED) 468 cksum = adler32(adler32(0, NULL, 0), state->out_block, 469 state->uncompressed_size); 470 else 471 cksum = state->uncompressed_cksum; 472 if (cksum != state->uncompressed_cksum) { 473 archive_set_error(&self->archive->archive, 474 ARCHIVE_ERRNO_MISC, "Corrupted data"); 475 return (ARCHIVE_FATAL); 476 } 477 478 __archive_read_filter_consume(self->upstream, state->compressed_size); 479 *p = state->out_block; 480 state->total_out += out_size; 481 return ((ssize_t)out_size); 482} 483 484/* 485 * Clean up the decompressor. 486 */ 487static int 488lzop_filter_close(struct archive_read_filter *self) 489{ 490 struct read_lzop *state = (struct read_lzop *)self->data; 491 492 free(state->out_block); 493 free(state); 494 return (ARCHIVE_OK); 495} 496 497#endif 498