Path: blob/main/contrib/llvm-project/lldb/source/Host/common/LZMA.cpp
39608 views
//===-- LZMA.cpp ----------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Host/Config.h"9#include "llvm/ADT/StringRef.h"10#include "llvm/Support/Error.h"1112#if LLDB_ENABLE_LZMA13#include <lzma.h>14#endif // LLDB_ENABLE_LZMA1516namespace lldb_private {1718namespace lzma {1920#if !LLDB_ENABLE_LZMA21bool isAvailable() { return false; }22llvm::Expected<uint64_t>23getUncompressedSize(llvm::ArrayRef<uint8_t> InputBuffer) {24llvm_unreachable("lzma::getUncompressedSize is unavailable");25}2627llvm::Error uncompress(llvm::ArrayRef<uint8_t> InputBuffer,28llvm::SmallVectorImpl<uint8_t> &Uncompressed) {29llvm_unreachable("lzma::uncompress is unavailable");30}3132#else // LLDB_ENABLE_LZMA3334bool isAvailable() { return true; }3536static const char *convertLZMACodeToString(lzma_ret Code) {37switch (Code) {38case LZMA_STREAM_END:39return "lzma error: LZMA_STREAM_END";40case LZMA_NO_CHECK:41return "lzma error: LZMA_NO_CHECK";42case LZMA_UNSUPPORTED_CHECK:43return "lzma error: LZMA_UNSUPPORTED_CHECK";44case LZMA_GET_CHECK:45return "lzma error: LZMA_GET_CHECK";46case LZMA_MEM_ERROR:47return "lzma error: LZMA_MEM_ERROR";48case LZMA_MEMLIMIT_ERROR:49return "lzma error: LZMA_MEMLIMIT_ERROR";50case LZMA_FORMAT_ERROR:51return "lzma error: LZMA_FORMAT_ERROR";52case LZMA_OPTIONS_ERROR:53return "lzma error: LZMA_OPTIONS_ERROR";54case LZMA_DATA_ERROR:55return "lzma error: LZMA_DATA_ERROR";56case LZMA_BUF_ERROR:57return "lzma error: LZMA_BUF_ERROR";58case LZMA_PROG_ERROR:59return "lzma error: LZMA_PROG_ERROR";60default:61llvm_unreachable("unknown or unexpected lzma status code");62}63}6465llvm::Expected<uint64_t>66getUncompressedSize(llvm::ArrayRef<uint8_t> InputBuffer) {67lzma_stream_flags opts{};68if (InputBuffer.size() < LZMA_STREAM_HEADER_SIZE) {69return llvm::createStringError(70llvm::inconvertibleErrorCode(),71"size of xz-compressed blob (%lu bytes) is smaller than the "72"LZMA_STREAM_HEADER_SIZE (%lu bytes)",73InputBuffer.size(), LZMA_STREAM_HEADER_SIZE);74}7576// Decode xz footer.77lzma_ret xzerr = lzma_stream_footer_decode(78&opts, InputBuffer.take_back(LZMA_STREAM_HEADER_SIZE).data());79if (xzerr != LZMA_OK) {80return llvm::createStringError(llvm::inconvertibleErrorCode(),81"lzma_stream_footer_decode()=%s",82convertLZMACodeToString(xzerr));83}84if (InputBuffer.size() < (opts.backward_size + LZMA_STREAM_HEADER_SIZE)) {85return llvm::createStringError(86llvm::inconvertibleErrorCode(),87"xz-compressed buffer size (%lu bytes) too small (required at "88"least %lu bytes) ",89InputBuffer.size(), (opts.backward_size + LZMA_STREAM_HEADER_SIZE));90}9192// Decode xz index.93lzma_index *xzindex;94uint64_t memlimit(UINT64_MAX);95size_t inpos = 0;96xzerr = lzma_index_buffer_decode(97&xzindex, &memlimit, nullptr,98InputBuffer.take_back(LZMA_STREAM_HEADER_SIZE + opts.backward_size)99.data(),100&inpos, InputBuffer.size());101if (xzerr != LZMA_OK) {102return llvm::createStringError(llvm::inconvertibleErrorCode(),103"lzma_index_buffer_decode()=%s",104convertLZMACodeToString(xzerr));105}106107// Get size of uncompressed file to construct an in-memory buffer of the108// same size on the calling end (if needed).109uint64_t uncompressedSize = lzma_index_uncompressed_size(xzindex);110111// Deallocate xz index as it is no longer needed.112lzma_index_end(xzindex, nullptr);113114return uncompressedSize;115}116117llvm::Error uncompress(llvm::ArrayRef<uint8_t> InputBuffer,118llvm::SmallVectorImpl<uint8_t> &Uncompressed) {119llvm::Expected<uint64_t> uncompressedSize = getUncompressedSize(InputBuffer);120121if (auto err = uncompressedSize.takeError())122return err;123124Uncompressed.resize(*uncompressedSize);125126// Decompress xz buffer to buffer.127uint64_t memlimit = UINT64_MAX;128size_t inpos = 0;129size_t outpos = 0;130lzma_ret ret = lzma_stream_buffer_decode(131&memlimit, 0, nullptr, InputBuffer.data(), &inpos, InputBuffer.size(),132Uncompressed.data(), &outpos, Uncompressed.size());133if (ret != LZMA_OK) {134return llvm::createStringError(llvm::inconvertibleErrorCode(),135"lzma_stream_buffer_decode()=%s",136convertLZMACodeToString(ret));137}138139return llvm::Error::success();140}141142#endif // LLDB_ENABLE_LZMA143144} // end of namespace lzma145} // namespace lldb_private146147148