static void * lzma_open (struct bfd *nbfd, void *open_closure) { asection *section = open_closure; bfd_size_type size, offset; lzma_stream_flags options; gdb_byte footer[LZMA_STREAM_HEADER_SIZE]; gdb_byte *indexdata; lzma_index *index; int ret; uint64_t memlimit = UINT64_MAX; struct lzma_stream *lstream; size_t pos; size = bfd_get_section_size (section); offset = section->filepos + size - LZMA_STREAM_HEADER_SIZE; if (size < LZMA_STREAM_HEADER_SIZE || bfd_seek (section->owner, offset, SEEK_SET) != 0 || bfd_bread (footer, LZMA_STREAM_HEADER_SIZE, section->owner) != LZMA_STREAM_HEADER_SIZE || lzma_stream_footer_decode (&options, footer) != LZMA_OK || offset < options.backward_size) { bfd_set_error (bfd_error_wrong_format); return NULL; } offset -= options.backward_size; indexdata = xmalloc (options.backward_size); index = NULL; pos = 0; if (bfd_seek (section->owner, offset, SEEK_SET) != 0 || bfd_bread (indexdata, options.backward_size, section->owner) != options.backward_size || lzma_index_buffer_decode (&index, &memlimit, &gdb_lzma_allocator, indexdata, &pos, options.backward_size) != LZMA_OK || lzma_index_size (index) != options.backward_size) { xfree (indexdata); bfd_set_error (bfd_error_wrong_format); return NULL; } xfree (indexdata); lstream = xzalloc (sizeof (struct lzma_stream)); lstream->section = section; lstream->index = index; return lstream; }
static void test_code(lzma_index *i) { const size_t alloc_size = 128 * 1024; uint8_t *buf = malloc(alloc_size); expect(buf != NULL); // Encode lzma_stream strm = LZMA_STREAM_INIT; expect(lzma_index_encoder(&strm, i) == LZMA_OK); const lzma_vli index_size = lzma_index_size(i); succeed(coder_loop(&strm, NULL, 0, buf, index_size, LZMA_STREAM_END, LZMA_RUN)); // Decode lzma_index *d; expect(lzma_index_decoder(&strm, &d, MEMLIMIT) == LZMA_OK); expect(d == NULL); succeed(decoder_loop(&strm, buf, index_size)); expect(is_equal(i, d)); lzma_index_end(d, NULL); lzma_end(&strm); // Decode with hashing lzma_index_hash *h = lzma_index_hash_init(NULL, NULL); expect(h != NULL); lzma_index_iter r; lzma_index_iter_init(&r, i); while (!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)) expect(lzma_index_hash_append(h, r.block.unpadded_size, r.block.uncompressed_size) == LZMA_OK); size_t pos = 0; while (pos < index_size - 1) expect(lzma_index_hash_decode(h, buf, &pos, pos + 1) == LZMA_OK); expect(lzma_index_hash_decode(h, buf, &pos, pos + 1) == LZMA_STREAM_END); lzma_index_hash_end(h, NULL); // Encode buffer size_t buf_pos = 1; expect(lzma_index_buffer_encode(i, buf, &buf_pos, index_size) == LZMA_BUF_ERROR); expect(buf_pos == 1); succeed(lzma_index_buffer_encode(i, buf, &buf_pos, index_size + 1)); expect(buf_pos == index_size + 1); // Decode buffer buf_pos = 1; uint64_t memlimit = MEMLIMIT; expect(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos, index_size) == LZMA_DATA_ERROR); expect(buf_pos == 1); expect(d == NULL); succeed(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos, index_size + 1)); expect(buf_pos == index_size + 1); expect(is_equal(i, d)); lzma_index_end(d, NULL); free(buf); }
void* gar_map(char* filename, size_t* out_length) { uint8_t* in_data; size_t in_length; if (!(in_data = platform_map(filename, &in_length))) return NULL; switch (gar_identify(in_data)) { case gar_uncompressed: *out_length = in_length; return in_data; case gar_xz_compressed: { uint8_t* out_data; size_t in_pos = 0; size_t out_pos = 0; uint8_t* ptr; uint64_t memlimit = 134217728; lzma_stream_flags flags; lzma_index *index; if ((ptr = in_data + in_length - 12) < in_data) goto error; if (lzma_stream_footer_decode(&flags, ptr) != LZMA_OK) goto error; if ((ptr -= flags.backward_size) < in_data) goto error; if (lzma_index_buffer_decode(&index, &memlimit, NULL, ptr, &in_pos, in_length - (ptr - in_data)) != LZMA_OK) goto error; memlimit = 134217728; *out_length = lzma_index_uncompressed_size(index); if (!(out_data = platform_virtualalloc(*out_length, mem_read | mem_write))) { lzma_index_end(index, NULL); goto error; } in_pos = 0; if (lzma_stream_buffer_decode(&memlimit, 0, NULL, in_data, &in_pos, in_length, out_data, &out_pos, *out_length) == LZMA_OK) { lzma_index_end(index, NULL); platform_unmap(in_data, in_length); if (gar_identify(out_data) != gar_uncompressed) { platform_virtualfree(out_data, *out_length); return NULL; } out_data[0] = 'a'; out_data[1] = 'n'; out_data[2] = 'o'; out_data[3] = 'n'; platform_virtualprotect(out_data, *out_length, mem_read); return out_data; } platform_virtualfree(out_data, *out_length); error: platform_unmap(in_data, in_length); return NULL; } default: platform_unmap(in_data, in_length); return NULL; } }