diff options
Diffstat (limited to 'src/lib/compression')
-rw-r--r-- | src/lib/compression/bzip2/bzip2.cpp | 3 | ||||
-rw-r--r-- | src/lib/compression/compress_utils.cpp | 189 | ||||
-rw-r--r-- | src/lib/compression/compress_utils.h | 5 | ||||
-rw-r--r-- | src/lib/compression/compression.cpp | 266 | ||||
-rw-r--r-- | src/lib/compression/compression.h | 9 | ||||
-rw-r--r-- | src/lib/compression/lzma/lzma.cpp | 3 | ||||
-rw-r--r-- | src/lib/compression/zlib/zlib.cpp | 5 |
7 files changed, 248 insertions, 232 deletions
diff --git a/src/lib/compression/bzip2/bzip2.cpp b/src/lib/compression/bzip2/bzip2.cpp index 565eb09fc..1d1af7e29 100644 --- a/src/lib/compression/bzip2/bzip2.cpp +++ b/src/lib/compression/bzip2/bzip2.cpp @@ -8,6 +8,7 @@ */ #include <botan/bzip2.h> +#include <botan/exceptn.h> #include <botan/internal/compress_utils.h> #define BZ_NO_STDIO @@ -15,8 +16,6 @@ namespace Botan { -BOTAN_REGISTER_COMPRESSION(Bzip2_Compression, Bzip2_Decompression); - namespace { class Bzip2_Stream : public Zlib_Style_Stream<bz_stream, char> diff --git a/src/lib/compression/compress_utils.cpp b/src/lib/compression/compress_utils.cpp new file mode 100644 index 000000000..2af629b9c --- /dev/null +++ b/src/lib/compression/compress_utils.cpp @@ -0,0 +1,189 @@ +/* +* Compression Utils +* (C) 2014,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/internal/compress_utils.h> +#include <botan/exceptn.h> + +namespace Botan { + +void* Compression_Alloc_Info::do_malloc(size_t n, size_t size) + { + const size_t total_size = n * size; + + BOTAN_ASSERT_EQUAL(total_size / size, n, "Overflow check"); + + // TODO maximum length check here? + + void* ptr = std::malloc(total_size); + + /* + * Return null rather than throwing here as we are being called by a + * C library and it may not be possible for an exception to unwind + * the call stack from here. The compression library is expecting a + * function written in C and a null return on error, which it will + * send upwards to the compression wrappers. + */ + + if(ptr) + { + std::memset(ptr, 0, total_size); + m_current_allocs[ptr] = total_size; + } + + return ptr; + } + +void Compression_Alloc_Info::do_free(void* ptr) + { + if(ptr) + { + auto i = m_current_allocs.find(ptr); + + if(i == m_current_allocs.end()) + throw Exception("Compression_Alloc_Info::free got pointer not allocated by us"); + + zero_mem(ptr, i->second); + std::free(ptr); + m_current_allocs.erase(i); + } + } + +void Stream_Compression::clear() + { + m_stream.reset(); + } + +void Stream_Compression::start(size_t level) + { + m_stream.reset(make_stream(level)); + } + +void Stream_Compression::process(secure_vector<byte>& buf, size_t offset, u32bit flags) + { + BOTAN_ASSERT(m_stream, "Initialized"); + BOTAN_ASSERT(buf.size() >= offset, "Offset is sane"); + + if(m_buffer.size() < buf.size() + offset) + m_buffer.resize(buf.size() + offset); + + // If the output buffer has zero length, .data() might return nullptr. This would + // make some compression algorithms (notably those provided by zlib) fail. + // Any small positive value works fine, but we choose 32 as it is the smallest power + // of two that is large enough to hold all the headers and trailers of the common + // formats, preventing further resizings to make room for output data. + if(m_buffer.size() == 0) + m_buffer.resize(32); + + m_stream->next_in(buf.data() + offset, buf.size() - offset); + m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); + + while(true) + { + m_stream->run(flags); + + if(m_stream->avail_out() == 0) + { + const size_t added = 8 + m_buffer.size(); + m_buffer.resize(m_buffer.size() + added); + m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); + } + else if(m_stream->avail_in() == 0) + { + m_buffer.resize(m_buffer.size() - m_stream->avail_out()); + break; + } + } + + copy_mem(m_buffer.data(), buf.data(), offset); + buf.swap(m_buffer); + } + +void Stream_Compression::update(secure_vector<byte>& buf, size_t offset, bool flush) + { + BOTAN_ASSERT(m_stream, "Initialized"); + process(buf, offset, flush ? m_stream->flush_flag() : m_stream->run_flag()); + } + +void Stream_Compression::finish(secure_vector<byte>& buf, size_t offset) + { + BOTAN_ASSERT(m_stream, "Initialized"); + process(buf, offset, m_stream->finish_flag()); + clear(); + } + +void Stream_Decompression::clear() + { + m_stream.reset(); + } + +void Stream_Decompression::start() + { + m_stream.reset(make_stream()); + } + +void Stream_Decompression::process(secure_vector<byte>& buf, size_t offset, u32bit flags) + { + BOTAN_ASSERT(m_stream, "Initialized"); + BOTAN_ASSERT(buf.size() >= offset, "Offset is sane"); + + if(m_buffer.size() < buf.size() + offset) + m_buffer.resize(buf.size() + offset); + + m_stream->next_in(buf.data() + offset, buf.size() - offset); + m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); + + while(true) + { + const bool stream_end = m_stream->run(flags); + + if(stream_end) + { + if(m_stream->avail_in() == 0) // all data consumed? + { + m_buffer.resize(m_buffer.size() - m_stream->avail_out()); + clear(); + break; + } + + // More data follows: try to process as a following stream + const size_t read = (buf.size() - offset) - m_stream->avail_in(); + start(); + m_stream->next_in(buf.data() + offset + read, buf.size() - offset - read); + } + + if(m_stream->avail_out() == 0) + { + const size_t added = 8 + m_buffer.size(); + m_buffer.resize(m_buffer.size() + added); + m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); + } + else if(m_stream->avail_in() == 0) + { + m_buffer.resize(m_buffer.size() - m_stream->avail_out()); + break; + } + } + + copy_mem(m_buffer.data(), buf.data(), offset); + buf.swap(m_buffer); + } + +void Stream_Decompression::update(secure_vector<byte>& buf, size_t offset) + { + process(buf, offset, m_stream->run_flag()); + } + +void Stream_Decompression::finish(secure_vector<byte>& buf, size_t offset) + { + if(buf.size() != offset || m_stream.get()) + process(buf, offset, m_stream->finish_flag()); + + if(m_stream.get()) + throw Exception(name() + " finished but not at stream end"); + } + +} diff --git a/src/lib/compression/compress_utils.h b/src/lib/compression/compress_utils.h index a60ae3c22..9f6871a0b 100644 --- a/src/lib/compression/compress_utils.h +++ b/src/lib/compression/compress_utils.h @@ -9,7 +9,6 @@ #define BOTAN_COMPRESSION_UTILS_H__ #include <botan/compression.h> -#include <botan/internal/algo_registry.h> #include <memory> #include <unordered_map> @@ -85,10 +84,6 @@ class Zlib_Style_Stream : public Compression_Stream std::unique_ptr<Compression_Alloc_Info> m_allocs; }; -#define BOTAN_REGISTER_COMPRESSION(C, D) \ - BOTAN_REGISTER_T_NOARGS(Compression_Algorithm, C); \ - BOTAN_REGISTER_T_NOARGS(Decompression_Algorithm, D) - } #endif diff --git a/src/lib/compression/compression.cpp b/src/lib/compression/compression.cpp index f289aa79f..92004a071 100644 --- a/src/lib/compression/compression.cpp +++ b/src/lib/compression/compression.cpp @@ -1,233 +1,75 @@ /* -* Compression Transform -* (C) 2014 Jack Lloyd +* Compression Factory +* (C) 2014,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include <botan/compression.h> -#include <botan/internal/compress_utils.h> #include <botan/mem_ops.h> #include <cstdlib> -namespace Botan { - -void* Compression_Alloc_Info::do_malloc(size_t n, size_t size) - { - const size_t total_size = n * size; - - BOTAN_ASSERT_EQUAL(total_size / size, n, "Overflow check"); - - // TODO maximum length check here? - - void* ptr = std::malloc(total_size); - - /* - * Return null rather than throwing here as we are being called by a - * C library and it may not be possible for an exception to unwind - * the call stack from here. The compression library is expecting a - * function written in C and a null return on error, which it will - * send upwards to the compression wrappers. - */ - - if(ptr) - { - std::memset(ptr, 0, total_size); - m_current_allocs[ptr] = total_size; - } - - return ptr; - } - -void Compression_Alloc_Info::do_free(void* ptr) - { - if(ptr) - { - auto i = m_current_allocs.find(ptr); - - if(i == m_current_allocs.end()) - throw Exception("Compression_Alloc_Info::free got pointer not allocated by us"); - - zero_mem(ptr, i->second); - std::free(ptr); - m_current_allocs.erase(i); - } - } - -Compression_Algorithm* make_compressor(const std::string& type) - { - const std::map<std::string, std::string> trans{ - {"zlib", "Zlib"}, - {"deflate", "Deflate"}, - {"gzip", "Gzip"}, - {"gz", "Gzip"}, - {"bzip2", "Bzip2"}, - {"bz2", "Bzip2"}, - {"lzma", "LZMA"}, - {"xz", "LZMA"}}; - - auto i = trans.find(type); - - if(i == trans.end()) - return nullptr; - - const SCAN_Name t_name(i->second + "_Compression"); - return Algo_Registry<Compression_Algorithm>::global_registry().make(t_name); - } - -Decompression_Algorithm* make_decompressor(const std::string& type) - { - const std::map<std::string, std::string> trans{ - {"zlib", "Zlib"}, - {"deflate", "Deflate"}, - {"gzip", "Gzip"}, - {"gz", "Gzip"}, - {"bzip2", "Bzip2"}, - {"bz2", "Bzip2"}, - {"lzma", "LZMA"}, - {"xz", "LZMA"}}; - - auto i = trans.find(type); - - if(i == trans.end()) - return nullptr; - - const SCAN_Name t_name(i->second + "_Decompression"); - return Algo_Registry<Decompression_Algorithm>::global_registry().make(t_name); - } - -void Stream_Compression::clear() - { - m_stream.reset(); - } - -void Stream_Compression::start(size_t level) - { - m_stream.reset(make_stream(level)); - } - -void Stream_Compression::process(secure_vector<byte>& buf, size_t offset, u32bit flags) - { - BOTAN_ASSERT(m_stream, "Initialized"); - BOTAN_ASSERT(buf.size() >= offset, "Offset is sane"); - - if(m_buffer.size() < buf.size() + offset) - m_buffer.resize(buf.size() + offset); - - // If the output buffer has zero length, .data() might return nullptr. This would - // make some compression algorithms (notably those provided by zlib) fail. - // Any small positive value works fine, but we choose 32 as it is the smallest power - // of two that is large enough to hold all the headers and trailers of the common - // formats, preventing further resizings to make room for output data. - if(m_buffer.size() == 0) - m_buffer.resize(32); - - m_stream->next_in(buf.data() + offset, buf.size() - offset); - m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); - - while(true) - { - m_stream->run(flags); +#if defined(BOTAN_HAS_ZLIB) + #include <botan/zlib.h> +#endif - if(m_stream->avail_out() == 0) - { - const size_t added = 8 + m_buffer.size(); - m_buffer.resize(m_buffer.size() + added); - m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); - } - else if(m_stream->avail_in() == 0) - { - m_buffer.resize(m_buffer.size() - m_stream->avail_out()); - break; - } - } +#if defined(BOTAN_HAS_BZIP2) + #include <botan/bzip2.h> +#endif - copy_mem(m_buffer.data(), buf.data(), offset); - buf.swap(m_buffer); - } - -void Stream_Compression::update(secure_vector<byte>& buf, size_t offset, bool flush) - { - BOTAN_ASSERT(m_stream, "Initialized"); - process(buf, offset, flush ? m_stream->flush_flag() : m_stream->run_flag()); - } +#if defined(BOTAN_HAS_LZMA) + #include <botan/lzma.h> +#endif -void Stream_Compression::finish(secure_vector<byte>& buf, size_t offset) - { - BOTAN_ASSERT(m_stream, "Initialized"); - process(buf, offset, m_stream->finish_flag()); - clear(); - } - -void Stream_Decompression::clear() - { - m_stream.reset(); - } +namespace Botan { -void Stream_Decompression::start() +Compression_Algorithm* make_compressor(const std::string& name) { - m_stream.reset(make_stream()); +#if defined(BOTAN_HAS_ZLIB) + if(name == "Zlib" || name == "zlib") + return new Zlib_Compression; + if(name == "Gzip" || name == "gzip" || name == "gz") + return new Gzip_Compression; + if(name == "Deflate" || name == "deflate") + return new Deflate_Compression; +#endif + +#if defined(BOTAN_HAS_BZIP2) + if(name == "bzip2" || name == "bz2" || name == "Bzip2") + return new Bzip2_Compression; +#endif + +#if defined(BOTAN_HAS_LZMA) + if(name == "lzma" || name == "xz" || name == "LZMA") + return new LZMA_Compression; +#endif + + return nullptr; } -void Stream_Decompression::process(secure_vector<byte>& buf, size_t offset, u32bit flags) +Decompression_Algorithm* make_decompressor(const std::string& name) { - BOTAN_ASSERT(m_stream, "Initialized"); - BOTAN_ASSERT(buf.size() >= offset, "Offset is sane"); - - if(m_buffer.size() < buf.size() + offset) - m_buffer.resize(buf.size() + offset); - - m_stream->next_in(buf.data() + offset, buf.size() - offset); - m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); - - while(true) - { - const bool stream_end = m_stream->run(flags); - - if(stream_end) - { - if(m_stream->avail_in() == 0) // all data consumed? - { - m_buffer.resize(m_buffer.size() - m_stream->avail_out()); - clear(); - break; - } - - // More data follows: try to process as a following stream - const size_t read = (buf.size() - offset) - m_stream->avail_in(); - start(); - m_stream->next_in(buf.data() + offset + read, buf.size() - offset - read); - } - - if(m_stream->avail_out() == 0) - { - const size_t added = 8 + m_buffer.size(); - m_buffer.resize(m_buffer.size() + added); - m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); - } - else if(m_stream->avail_in() == 0) - { - m_buffer.resize(m_buffer.size() - m_stream->avail_out()); - break; - } - } - - copy_mem(m_buffer.data(), buf.data(), offset); - buf.swap(m_buffer); - } - -void Stream_Decompression::update(secure_vector<byte>& buf, size_t offset) - { - process(buf, offset, m_stream->run_flag()); +#if defined(BOTAN_HAS_ZLIB) + if(name == "Zlib" || name == "zlib") + return new Zlib_Decompression; + if(name == "Gzip" || name == "gzip" || name == "gz") + return new Gzip_Decompression; + if(name == "Deflate" || name == "deflate") + return new Deflate_Decompression; +#endif + +#if defined(BOTAN_HAS_BZIP2) + if(name == "bzip2" || name == "bz2" || name == "Bzip2") + return new Bzip2_Decompression; +#endif + +#if defined(BOTAN_HAS_LZMA) + if(name == "lzma" || name == "xz" || name == "LZMA") + return new LZMA_Decompression; +#endif + + return nullptr; } -void Stream_Decompression::finish(secure_vector<byte>& buf, size_t offset) - { - if(buf.size() != offset || m_stream.get()) - process(buf, offset, m_stream->finish_flag()); - - if(m_stream.get()) - throw Exception(name() + " finished but not at stream end"); - } } diff --git a/src/lib/compression/compression.h b/src/lib/compression/compression.h index f135f6d04..693772b6a 100644 --- a/src/lib/compression/compression.h +++ b/src/lib/compression/compression.h @@ -9,7 +9,6 @@ #define BOTAN_COMPRESSION_TRANSFORM_H__ #include <botan/secmem.h> -#include <botan/scan_name.h> namespace Botan { @@ -19,8 +18,6 @@ namespace Botan { class BOTAN_DLL Compression_Algorithm { public: - typedef SCAN_Name Spec; - /** * Begin compressing. Most compression algorithms offer a tunable * time/compression tradeoff parameter generally represented by @@ -67,8 +64,6 @@ class BOTAN_DLL Compression_Algorithm class BOTAN_DLL Decompression_Algorithm { public: - typedef SCAN_Name Spec; - /** * Begin decompressing. * Decompression does not support levels, as compression does. @@ -108,7 +103,7 @@ BOTAN_DLL Compression_Algorithm* make_compressor(const std::string& type); BOTAN_DLL Decompression_Algorithm* make_decompressor(const std::string& type); /** -* FIXME add doc +* Adapts a zlib style API */ class Compression_Stream { @@ -131,7 +126,7 @@ class Compression_Stream }; /** -* FIXME add doc +* Used to implement compression using Compression_Stream */ class Stream_Compression : public Compression_Algorithm { diff --git a/src/lib/compression/lzma/lzma.cpp b/src/lib/compression/lzma/lzma.cpp index 18701278d..3831ef68c 100644 --- a/src/lib/compression/lzma/lzma.cpp +++ b/src/lib/compression/lzma/lzma.cpp @@ -10,12 +10,11 @@ #include <botan/lzma.h> #include <botan/internal/compress_utils.h> +#include <botan/exceptn.h> #include <lzma.h> namespace Botan { -BOTAN_REGISTER_COMPRESSION(LZMA_Compression, LZMA_Decompression); - namespace { class LZMA_Stream : public Zlib_Style_Stream<lzma_stream, byte> diff --git a/src/lib/compression/zlib/zlib.cpp b/src/lib/compression/zlib/zlib.cpp index 836925a68..27ae6fb20 100644 --- a/src/lib/compression/zlib/zlib.cpp +++ b/src/lib/compression/zlib/zlib.cpp @@ -9,15 +9,12 @@ #include <botan/zlib.h> #include <botan/internal/compress_utils.h> +#include <botan/exceptn.h> #include <ctime> #include <zlib.h> namespace Botan { -BOTAN_REGISTER_COMPRESSION(Zlib_Compression, Zlib_Decompression); -BOTAN_REGISTER_COMPRESSION(Gzip_Compression, Gzip_Decompression); -BOTAN_REGISTER_COMPRESSION(Deflate_Compression, Deflate_Decompression); - namespace { class Zlib_Stream : public Zlib_Style_Stream<z_stream, Bytef> |