lzma_filter_flags_decode( lzma_filter *filter, lzma_allocator *allocator, const uint8_t *in, size_t *in_pos, size_t in_size) { lzma_vli props_size; lzma_ret ret; // Set the pointer to NULL so the caller can always safely free it. filter->options = NULL; // Filter ID return_if_error(lzma_vli_decode(&filter->id, NULL, in, in_pos, in_size)); if (filter->id >= LZMA_FILTER_RESERVED_START) return LZMA_DATA_ERROR; // Size of Properties return_if_error(lzma_vli_decode(&props_size, NULL, in, in_pos, in_size)); // Filter Properties if (in_size - *in_pos < props_size) return LZMA_DATA_ERROR; ret = lzma_properties_decode( filter, allocator, in + *in_pos, props_size); *in_pos += props_size; return ret; }
/// Return true if the data in in_buf seems to be in the .lzma format. static bool is_format_lzma(void) { // The .lzma header is 13 bytes. if (strm.avail_in < 13) { return false; } // Decode the LZMA1 properties. lzma_filter filter = { .id = LZMA_FILTER_LZMA1 }; if (lzma_properties_decode(&filter, NULL, in_buf.u8, 5) != LZMA_OK) { return false; } // A hack to ditch tons of false positives: We allow only dictionary // sizes that are 2^n or 2^n + 2^(n-1) or UINT32_MAX. LZMA_Alone // created only files with 2^n, but accepts any dictionary size. // If someone complains, this will be reconsidered. lzma_options_lzma *opt = filter.options; const uint32_t dict_size = opt->dict_size; free(opt); if (dict_size != UINT32_MAX) { uint32_t d = dict_size - 1; d |= d >> 2; d |= d >> 3; d |= d >> 4; d |= d >> 8; d |= d >> 16; ++d; if (d != dict_size || dict_size == 0) return false; }
// refer to src/xz/coder.c in XZ Utils. int CTarArcFile_Lzma::check_head_format(unsigned char *buf, size_t buf_size, int format_type) { if(buf_size>=6 && memcmp(buf, "\3757zXZ", 6) == 0){ if(format_type>=0) { return format_type==ARCHIVETYPE_XZ; } else { return ARCHIVETYPE_XZ; } } while(buf_size>=13){ lzma_filter filter; filter.id = LZMA_FILTER_LZMA1; if(lzma_properties_decode(&filter, NULL, buf, 5) != LZMA_OK){ break; } lzma_options_lzma *opt = (lzma_options_lzma *)(filter.options); const uint32_t dict_size = opt->dict_size; // free(opt); if (dict_size != UINT32_MAX) { uint32_t d = dict_size - 1; d |= d >> 2; d |= d >> 3; d |= d >> 4; d |= d >> 8; d |= d >> 16; ++d; if (d != dict_size || dict_size == 0) break; } uint64_t uncompressed_size = 0; for (size_t i = 0; i < 8; ++i) uncompressed_size |= (uint64_t)(buf[5 + i]) << (i * 8); if (uncompressed_size != UINT64_MAX && uncompressed_size > (UINT64_C(1) << 38)){ break; } if(format_type>=0) { return format_type==ARCHIVETYPE_LZMA; } else { return ARCHIVETYPE_LZMA; } }
static PyObject * _lzma__decode_filter_properties_impl(PyModuleDef *module, lzma_vli filter_id, Py_buffer *encoded_props) /*[clinic end generated code: output=235f7f5345d48744 input=246410800782160c]*/ { lzma_filter filter; lzma_ret lzret; PyObject *result = NULL; filter.id = filter_id; lzret = lzma_properties_decode( &filter, NULL, encoded_props->buf, encoded_props->len); if (catch_lzma_error(lzret)) return NULL; result = build_filter_spec(&filter); /* We use vanilla free() here instead of PyMem_Free() - filter.options was allocated by lzma_properties_decode() using the default allocator. */ free(filter.options); return result; }
/// Parse the .lzma header and display information about it. static bool lzmainfo(const char *name, FILE *f) { uint8_t buf[13]; const size_t size = fread(buf, 1, sizeof(buf), f); if (size != 13) { fprintf(stderr, "%s: %s: %s\n", progname, name, ferror(f) ? strerror(errno) : _("File is too small to be a .lzma file")); return true; } lzma_filter filter = { .id = LZMA_FILTER_LZMA1 }; // Parse the first five bytes. switch (lzma_properties_decode(&filter, NULL, buf, 5)) { case LZMA_OK: break; case LZMA_OPTIONS_ERROR: fprintf(stderr, "%s: %s: %s\n", progname, name, _("Not a .lzma file")); return true; case LZMA_MEM_ERROR: fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM)); exit(EXIT_FAILURE); default: fprintf(stderr, "%s: %s\n", progname, _("Internal error (bug)")); exit(EXIT_FAILURE); } // Uncompressed size uint64_t uncompressed_size = 0; for (size_t i = 0; i < 8; ++i) uncompressed_size |= (uint64_t)(buf[5 + i]) << (i * 8); // Display the results. We don't want to translate these and also // will use MB instead of MiB, because someone could be parsing // this output and we don't want to break that when people move // from LZMA Utils to XZ Utils. if (f != stdin) printf("%s\n", name); printf("Uncompressed size: "); if (uncompressed_size == UINT64_MAX) printf("Unknown"); else printf("%" PRIu64 " MB (%" PRIu64 " bytes)", (uncompressed_size + 512 * 1024) / (1024 * 1024), uncompressed_size); lzma_options_lzma *opt = filter.options; printf("\nDictionary size: " "%" PRIu32 " MB (2^%" PRIu32 " bytes)\n" "Literal context bits (lc): %" PRIu32 "\n" "Literal pos bits (lp): %" PRIu32 "\n" "Number of pos bits (pb): %" PRIu32 "\n", (opt->dict_size + 512 * 1024) / (1024 * 1024), my_log2(opt->dict_size), opt->lc, opt->lp, opt->pb); free(opt); return false; }