filter/Library_xsltfilter.mk | 1 filter/source/xsltfilter/OleHandler.cxx | 3 include/package/InflateZlib.hxx | 45 +++++ include/package/Inflater.hxx | 55 ++---- package/Library_package2.mk | 3 package/inc/InflaterBytesZlib.hxx | 41 ++++ package/inc/ZipFile.hxx | 3 package/source/zipapi/InflateZlib.cxx | 115 +++++++++++++ package/source/zipapi/Inflater.cxx | 239 ---------------------------- package/source/zipapi/InflaterBytesZlib.cxx | 105 ++++++++++++ package/source/zipapi/XUnbufferedStream.cxx | 16 - package/source/zipapi/XUnbufferedStream.hxx | 3 package/source/zipapi/ZipFile.cxx | 8 solenv/clang-format/excludelist | 4 14 files changed, 351 insertions(+), 290 deletions(-)
New commits: commit 3e1aa5805cb2339a55ffce0448e0b3b5d8efd3a6 Author: Akshay Kumar Dubey <akshaymani...@gmail.com> AuthorDate: Sun Mar 30 16:27:05 2025 +0530 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Tue Apr 29 09:38:52 2025 +0200 tdf#137308 - Part 1: Refactor Inflater classes for extensibility Refactor ZIP decompression classes (Inflater, InflaterBytes) to support multiple decompression algorithms, enabling future Zstandard support. Make Inflater and InflaterBytes abstract base classes defining a common interface. Move the original zlib/Deflate logic into new derived classes InflateZlib and InflaterBytesZlib. Update usage sites to instantiate the *Zlib variants via unique_ptr to the base class, preserving existing functionality. Move header files to standard locations (include/package, package/inc) and update includes and build files. This pure refactoring prepares the codebase for adding Zstandard (zstd) decompression. Correct a minor logical bug in the ZipFile::getSizeAndCRC loop condition. Change-Id: I9be3c02946e29eb2dae09f500eb47d8a4261af22 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183504 Reviewed-by: Devansh Varshney <varshney.devansh...@gmail.com> Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Michael Meeks <michael.me...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Tested-by: Jenkins diff --git a/filter/Library_xsltfilter.mk b/filter/Library_xsltfilter.mk index 42f426c945ea..a7062bac0e86 100644 --- a/filter/Library_xsltfilter.mk +++ b/filter/Library_xsltfilter.mk @@ -41,6 +41,7 @@ $(eval $(call gb_Library_use_externals,xsltfilter,\ libxml2 \ libxslt \ libexslt \ + zlib \ )) $(eval $(call gb_Library_add_exception_objects,xsltfilter,\ diff --git a/filter/source/xsltfilter/OleHandler.cxx b/filter/source/xsltfilter/OleHandler.cxx index feab2eec414c..abd8a7e9f208 100644 --- a/filter/source/xsltfilter/OleHandler.cxx +++ b/filter/source/xsltfilter/OleHandler.cxx @@ -28,6 +28,7 @@ #include "OleHandler.hxx" #include <optional> +#include <package/InflateZlib.hxx> using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; @@ -116,7 +117,7 @@ namespace XSLT } // Decompress the bytes - std::optional< ::ZipUtils::Inflater> decompresser(std::in_place, false); + std::unique_ptr< ::ZipUtils::Inflater> decompresser = std::make_unique< ::ZipUtils::InflateZlib>(false); decompresser->setInput(content); Sequence<sal_Int8> result(oleLength); decompresser->doInflateSegment(result, 0, oleLength); diff --git a/include/package/InflateZlib.hxx b/include/package/InflateZlib.hxx new file mode 100644 index 000000000000..f495453a779b --- /dev/null +++ b/include/package/InflateZlib.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <memory> +#include <package/Inflater.hxx> +#include <zlib.h> + +namespace ZipUtils +{ +class DLLPUBLIC_PACKAGE InflateZlib : public Inflater +{ +private: + bool bFinished; + bool bNeedDict; + sal_Int32 nOffset; + sal_Int32 nLength; + sal_Int32 nLastInflateError; + css::uno::Sequence<sal_Int8> sInBuffer; + std::unique_ptr<z_stream> pStream; + + sal_Int32 doInflateBytes(css::uno::Sequence<sal_Int8>& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength); + +public: + explicit InflateZlib(bool bNoWrap); + virtual ~InflateZlib() override; + + virtual void setInput(const css::uno::Sequence<sal_Int8>& rBuffer) override; + virtual bool needsDictionary() const override { return bNeedDict; } + virtual bool finished() const override { return bFinished; } + virtual sal_Int32 doInflateSegment(css::uno::Sequence<sal_Int8>& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength) override; + virtual void end() override final; + virtual sal_Int32 getLastInflateError() const override { return nLastInflateError; } +}; + +} // namespace ZipUtils + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/package/Inflater.hxx b/include/package/Inflater.hxx index c529b471cb6f..8e5cbfae2650 100644 --- a/include/package/Inflater.hxx +++ b/include/package/Inflater.hxx @@ -25,52 +25,35 @@ #include <package/packagedllapi.hxx> #include <memory> -struct z_stream_s; - namespace ZipUtils { -class UNLESS_MERGELIBS(DLLPUBLIC_PACKAGE) Inflater final +class UNLESS_MERGELIBS(DLLPUBLIC_PACKAGE) Inflater { - typedef struct z_stream_s z_stream; - - bool bFinished, bNeedDict; - sal_Int32 nOffset, nLength, nLastInflateError; - std::unique_ptr<z_stream> pStream; - css::uno::Sequence < sal_Int8 > sInBuffer; - sal_Int32 doInflateBytes (css::uno::Sequence < sal_Int8 > &rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength); - public: - Inflater(bool bNoWrap); - ~Inflater(); - void setInput( const css::uno::Sequence< sal_Int8 >& rBuffer ); - bool needsDictionary() const { return bNeedDict; } - bool finished() const { return bFinished; } - sal_Int32 doInflateSegment( css::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength ); - void end( ); - - sal_Int32 getLastInflateError() const { return nLastInflateError; } + Inflater() = default; + virtual ~Inflater() = default; + + virtual void setInput(const css::uno::Sequence<sal_Int8>& rBuffer) = 0; + virtual bool needsDictionary() const = 0; + virtual bool finished() const = 0; + virtual sal_Int32 doInflateSegment(css::uno::Sequence<sal_Int8>& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength) = 0; + virtual void end() = 0; + virtual sal_Int32 getLastInflateError() const = 0; }; -class UNLESS_MERGELIBS(DLLPUBLIC_PACKAGE) InflaterBytes final +class UNLESS_MERGELIBS(DLLPUBLIC_PACKAGE) InflaterBytes { - typedef struct z_stream_s z_stream; - - bool bFinished; - sal_Int32 nOffset, nLength; - std::unique_ptr<z_stream> pStream; - const sal_Int8* sInBuffer; - sal_Int32 doInflateBytes (sal_Int8* pOutBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength); - public: - InflaterBytes(); - ~InflaterBytes(); - void setInput( const sal_Int8* pBuffer, sal_Int32 nLen ); - bool finished() const { return bFinished; } - sal_Int32 doInflateSegment( sal_Int8* pOutBuffer, sal_Int32 nBufLen, sal_Int32 nNewOffset, sal_Int32 nNewLength ); - void end( ); + InflaterBytes() = default; + virtual ~InflaterBytes() = default; + + virtual void setInput(const sal_Int8* pBuffer, sal_Int32 nLen) = 0; + virtual bool finished() const = 0; + virtual sal_Int32 doInflateSegment(sal_Int8* pOutBuffer, sal_Int32 nBufLen, sal_Int32 nNewOffset, sal_Int32 nNewLength) = 0; + virtual void end() = 0; }; -} +} // namespace ZipUtils #endif diff --git a/package/Library_package2.mk b/package/Library_package2.mk index 16ef09af5f6d..a740d33fc757 100644 --- a/package/Library_package2.mk +++ b/package/Library_package2.mk @@ -55,7 +55,8 @@ $(eval $(call gb_Library_add_exception_objects,package2,\ package/source/zipapi/ByteGrabber \ package/source/zipapi/CRC32 \ package/source/zipapi/Deflater \ - package/source/zipapi/Inflater \ + package/source/zipapi/InflaterBytesZlib \ + package/source/zipapi/InflateZlib \ package/source/zipapi/sha1context \ package/source/zipapi/ThreadedDeflater \ package/source/zipapi/XBufferedThreadedStream \ diff --git a/package/inc/InflaterBytesZlib.hxx b/package/inc/InflaterBytesZlib.hxx new file mode 100644 index 000000000000..50da895e1b7a --- /dev/null +++ b/package/inc/InflaterBytesZlib.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <memory> +#include <package/Inflater.hxx> +#include <zlib.h> + +namespace ZipUtils +{ +class DLLPUBLIC_PACKAGE InflaterBytesZlib : public InflaterBytes +{ +private: + bool bFinished; + sal_Int32 nOffset; + sal_Int32 nLength; + const sal_Int8* sInBuffer; + std::unique_ptr<z_stream> pStream; + + sal_Int32 doInflateBytes(sal_Int8* pOutBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength); + +public: + InflaterBytesZlib(); + virtual ~InflaterBytesZlib() override; + + virtual void setInput(const sal_Int8* pBuffer, sal_Int32 nLen) override; + virtual bool finished() const override { return bFinished; } + virtual sal_Int32 doInflateSegment(sal_Int8* pOutBuffer, sal_Int32 nBufLen, sal_Int32 nNewOffset, sal_Int32 nNewLength) override; + virtual void end() override final; +}; + +} // namespace ZipUtils + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx index f496dfa2ce24..1252ae325df5 100644 --- a/package/inc/ZipFile.hxx +++ b/package/inc/ZipFile.hxx @@ -24,6 +24,7 @@ #include <comphelper/refcountedmutex.hxx> #include <package/Inflater.hxx> +#include <memory> #include <rtl/ref.hxx> #include "ByteGrabber.hxx" #include "HashMaps.hxx" @@ -61,7 +62,7 @@ private: EntryHash aEntries; ByteGrabber aGrabber; - ZipUtils::Inflater aInflater; + std::unique_ptr<ZipUtils::Inflater> aInflater; css::uno::Reference < css::io::XInputStream > xStream; const css::uno::Reference < css::uno::XComponentContext > m_xContext; diff --git a/package/source/zipapi/InflateZlib.cxx b/package/source/zipapi/InflateZlib.cxx new file mode 100644 index 000000000000..a7b2bb3643f4 --- /dev/null +++ b/package/source/zipapi/InflateZlib.cxx @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <package/InflateZlib.hxx> +#include <string.h> +#include <zlib.h> + +using namespace com::sun::star::uno; +using namespace ZipUtils; + +InflateZlib::InflateZlib(bool bNoWrap) + : bFinished(false), + bNeedDict(false), + nOffset(0), + nLength(0), + nLastInflateError(0), + pStream(std::make_unique<z_stream>()) +{ + memset(pStream.get(), 0, sizeof(*pStream)); + sal_Int32 nRes = inflateInit2(pStream.get(), bNoWrap ? -MAX_WBITS : MAX_WBITS); + switch (nRes) + { + case Z_OK: + break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: + pStream.reset(); + break; + default: + break; + } +} + +InflateZlib::~InflateZlib() +{ + end(); +} + +void InflateZlib::setInput(const Sequence<sal_Int8>& rBuffer) +{ + sInBuffer = rBuffer; + nOffset = 0; + nLength = rBuffer.getLength(); +} + +sal_Int32 InflateZlib::doInflateSegment(Sequence<sal_Int8>& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength) +{ + if (nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > rBuffer.getLength()) + { + return 0; + } + return doInflateBytes(rBuffer, nNewOffset, nNewLength); +} + +void InflateZlib::end() +{ + if (pStream) + { +#if !defined Z_PREFIX + inflateEnd(pStream.get()); +#else + z_inflateEnd(pStream.get()); +#endif + pStream.reset(); + } +} + +sal_Int32 InflateZlib::doInflateBytes(Sequence<sal_Int8>& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength) +{ + if (!pStream) + { + nLastInflateError = Z_STREAM_ERROR; + return 0; + } + nLastInflateError = 0; + + pStream->next_in = reinterpret_cast<const unsigned char*>(sInBuffer.getConstArray() + nOffset); + pStream->avail_in = nLength; + pStream->next_out = reinterpret_cast<unsigned char*>(rBuffer.getArray() + nNewOffset); + pStream->avail_out = nNewLength; + +#if !defined Z_PREFIX + sal_Int32 nResult = ::inflate(pStream.get(), Z_PARTIAL_FLUSH); +#else + sal_Int32 nResult = ::z_inflate(pStream.get(), Z_PARTIAL_FLUSH); +#endif + + switch (nResult) + { + case Z_STREAM_END: + bFinished = true; + [[fallthrough]]; + case Z_OK: + nOffset += nLength - pStream->avail_in; + nLength = pStream->avail_in; + return nNewLength - pStream->avail_out; + case Z_NEED_DICT: + bNeedDict = true; + nOffset += nLength - pStream->avail_in; + nLength = pStream->avail_in; + return 0; + default: + if (nLength && nNewLength) + nLastInflateError = nResult; + } + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/package/source/zipapi/Inflater.cxx b/package/source/zipapi/Inflater.cxx deleted file mode 100644 index 3c2a59d78111..000000000000 --- a/package/source/zipapi/Inflater.cxx +++ /dev/null @@ -1,239 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <package/Inflater.hxx> -#include <zlib.h> -#include <string.h> - -using namespace com::sun::star::uno; -using namespace ZipUtils; - -/** Provides general purpose decompression using the ZLIB library */ - -Inflater::Inflater(bool bNoWrap) -: bFinished(false), - bNeedDict(false), - nOffset(0), - nLength(0), - nLastInflateError(0) -{ - pStream.reset(new z_stream); - /* memset to 0 to set zalloc/opaque etc */ - memset (pStream.get(), 0, sizeof(*pStream)); - sal_Int32 nRes; - nRes = inflateInit2(pStream.get(), bNoWrap ? -MAX_WBITS : MAX_WBITS); - switch (nRes) - { - case Z_OK: - break; - case Z_MEM_ERROR: - pStream.reset(); - break; - case Z_STREAM_ERROR: - pStream.reset(); - break; - default: - break; - } -} - -Inflater::~Inflater() -{ - end(); -} - -void Inflater::setInput( const Sequence< sal_Int8 >& rBuffer ) -{ - sInBuffer = rBuffer; - nOffset = 0; - nLength = rBuffer.getLength(); -} - - -sal_Int32 Inflater::doInflateSegment( Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength ) -{ - if (nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > rBuffer.getLength()) - { - // do error handling - } - return doInflateBytes(rBuffer, nNewOffset, nNewLength); -} - -void Inflater::end( ) -{ - if (pStream) - { -#if !defined Z_PREFIX - inflateEnd(pStream.get()); -#else - z_inflateEnd(pStream.get()); -#endif - pStream.reset(); - } -} - -sal_Int32 Inflater::doInflateBytes (Sequence < sal_Int8 > &rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength) -{ - if ( !pStream ) - { - nLastInflateError = Z_STREAM_ERROR; - return 0; - } - - nLastInflateError = 0; - - pStream->next_in = reinterpret_cast<const unsigned char*>( sInBuffer.getConstArray() + nOffset ); - pStream->avail_in = nLength; - pStream->next_out = reinterpret_cast < unsigned char* > ( rBuffer.getArray() + nNewOffset ); - pStream->avail_out = nNewLength; - -#if !defined Z_PREFIX - sal_Int32 nResult = ::inflate(pStream.get(), Z_PARTIAL_FLUSH); -#else - sal_Int32 nResult = ::z_inflate(pStream.get(), Z_PARTIAL_FLUSH); -#endif - - switch (nResult) - { - case Z_STREAM_END: - bFinished = true; - [[fallthrough]]; - case Z_OK: - nOffset += nLength - pStream->avail_in; - nLength = pStream->avail_in; - return nNewLength - pStream->avail_out; - - case Z_NEED_DICT: - bNeedDict = true; - nOffset += nLength - pStream->avail_in; - nLength = pStream->avail_in; - return 0; - - default: - // it is no error, if there is no input or no output - if ( nLength && nNewLength ) - nLastInflateError = nResult; - } - - return 0; -} - -InflaterBytes::InflaterBytes() -: bFinished(false), - nOffset(0), - nLength(0), - sInBuffer(nullptr) -{ - pStream.reset(new z_stream); - /* memset to 0 to set zalloc/opaque etc */ - memset (pStream.get(), 0, sizeof(*pStream)); - sal_Int32 nRes; - nRes = inflateInit2(pStream.get(), -MAX_WBITS); - switch (nRes) - { - case Z_OK: - break; - case Z_MEM_ERROR: - pStream.reset(); - break; - case Z_STREAM_ERROR: - pStream.reset(); - break; - default: - break; - } -} - -InflaterBytes::~InflaterBytes() -{ - end(); -} - -void InflaterBytes::setInput( const sal_Int8* rBuffer, sal_Int32 nBufLen ) -{ - sInBuffer = rBuffer; - nOffset = 0; - nLength = nBufLen; -} - - -sal_Int32 InflaterBytes::doInflateSegment( sal_Int8* pOutBuffer, sal_Int32 nBufLen, sal_Int32 nNewOffset, sal_Int32 nNewLength ) -{ - if (nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > nBufLen) - { - // do error handling - } - return doInflateBytes(pOutBuffer, nNewOffset, nNewLength); -} - -void InflaterBytes::end( ) -{ - if (pStream) - { -#if !defined Z_PREFIX - inflateEnd(pStream.get()); -#else - z_inflateEnd(pStream.get()); -#endif - pStream.reset(); - } -} - -sal_Int32 InflaterBytes::doInflateBytes (sal_Int8* pOutBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength) -{ - if ( !pStream ) - { - return 0; - } - - pStream->next_in = reinterpret_cast<const unsigned char*>( sInBuffer + nOffset ); - pStream->avail_in = nLength; - pStream->next_out = reinterpret_cast < unsigned char* > ( pOutBuffer + nNewOffset ); - pStream->avail_out = nNewLength; - -#if !defined Z_PREFIX - sal_Int32 nResult = ::inflate(pStream.get(), Z_PARTIAL_FLUSH); -#else - sal_Int32 nResult = ::z_inflate(pStream.get(), Z_PARTIAL_FLUSH); -#endif - - switch (nResult) - { - case Z_STREAM_END: - bFinished = true; - [[fallthrough]]; - case Z_OK: - nOffset += nLength - pStream->avail_in; - nLength = pStream->avail_in; - return nNewLength - pStream->avail_out; - - case Z_NEED_DICT: - nOffset += nLength - pStream->avail_in; - nLength = pStream->avail_in; - return 0; - - default: - // it is no error, if there is no input or no output - break; - } - - return 0; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/InflaterBytesZlib.cxx b/package/source/zipapi/InflaterBytesZlib.cxx new file mode 100644 index 000000000000..941d4cfd2c57 --- /dev/null +++ b/package/source/zipapi/InflaterBytesZlib.cxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <cstring> +#include <InflaterBytesZlib.hxx> +#include <string.h> +#include <zlib.h> + +using namespace ZipUtils; + +InflaterBytesZlib::InflaterBytesZlib() + : bFinished(false), + nOffset(0), + nLength(0), + sInBuffer(nullptr), + pStream(std::make_unique<z_stream>()) +{ + memset(pStream.get(), 0, sizeof(*pStream)); + sal_Int32 nRes = inflateInit2(pStream.get(), -MAX_WBITS); + switch (nRes) + { + case Z_OK: + break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: + pStream.reset(); + break; + default: + break; + } +} + +InflaterBytesZlib::~InflaterBytesZlib() { end(); } + +void InflaterBytesZlib::setInput(const sal_Int8* rBuffer, sal_Int32 nBufLen) +{ + sInBuffer = rBuffer; + nOffset = 0; + nLength = nBufLen; +} + +sal_Int32 InflaterBytesZlib::doInflateSegment(sal_Int8* pOutBuffer, sal_Int32 nBufLen, sal_Int32 nNewOffset, sal_Int32 nNewLength) +{ + if (nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > nBufLen) + { + return 0; + } + return doInflateBytes(pOutBuffer, nNewOffset, nNewLength); +} + +void InflaterBytesZlib::end() +{ + if (pStream) + { +#if !defined Z_PREFIX + inflateEnd(pStream.get()); +#else + z_inflateEnd(pStream.get()); +#endif + pStream.reset(); + } +} + +sal_Int32 InflaterBytesZlib::doInflateBytes(sal_Int8* pOutBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength) +{ + if (!pStream) + return 0; + + pStream->next_in = reinterpret_cast<const unsigned char*>(sInBuffer + nOffset); + pStream->avail_in = nLength; + pStream->next_out = reinterpret_cast<unsigned char*>(pOutBuffer + nNewOffset); + pStream->avail_out = nNewLength; + +#if !defined Z_PREFIX + sal_Int32 nResult = ::inflate(pStream.get(), Z_PARTIAL_FLUSH); +#else + sal_Int32 nResult = ::z_inflate(pStream.get(), Z_PARTIAL_FLUSH); +#endif + + switch (nResult) + { + case Z_STREAM_END: + bFinished = true; + [[fallthrough]]; + case Z_OK: + nOffset += nLength - pStream->avail_in; + nLength = pStream->avail_in; + return nNewLength - pStream->avail_out; + case Z_NEED_DICT: + nOffset += nLength - pStream->avail_in; + nLength = pStream->avail_in; + return 0; + default: + break; + } + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/package/source/zipapi/XUnbufferedStream.cxx b/package/source/zipapi/XUnbufferedStream.cxx index 192958412d93..a5161adc36f0 100644 --- a/package/source/zipapi/XUnbufferedStream.cxx +++ b/package/source/zipapi/XUnbufferedStream.cxx @@ -23,16 +23,16 @@ #include "XUnbufferedStream.hxx" #include <EncryptionData.hxx> -#include <ZipFile.hxx> +#include <package/InflateZlib.hxx> #include <EncryptedDataHeader.hxx> #include <algorithm> #include <string.h> - #include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <osl/mutex.hxx> #include <utility> #include <comphelper/diagnose_ex.hxx> +#include <ZipFile.hxx> using namespace ::com::sun::star; using namespace com::sun::star::packages::zip::ZipConstants; @@ -55,7 +55,7 @@ XUnbufferedStream::XUnbufferedStream( , mxZipSeek ( xNewZipStream, UNO_QUERY ) , maEntry ( rEntry ) , mnBlockSize( 1 ) -, maInflater ( true ) +, maInflater( std::make_unique<ZipUtils::InflateZlib>(true) ) , mbRawStream ( nStreamMode == UNBUFF_STREAM_RAW || nStreamMode == UNBUFF_STREAM_WRAPPEDRAW ) , mbWrappedRaw ( nStreamMode == UNBUFF_STREAM_WRAPPEDRAW ) , mnHeaderToRead ( 0 ) @@ -126,7 +126,7 @@ XUnbufferedStream::XUnbufferedStream( , mxZipStream ( xRawStream ) , mxZipSeek ( xRawStream, UNO_QUERY ) , mnBlockSize( 1 ) -, maInflater ( true ) +, maInflater( std::make_unique<ZipUtils::InflateZlib>(true) ) , mbRawStream ( false ) , mbWrappedRaw ( false ) , mnHeaderToRead ( 0 ) @@ -231,7 +231,7 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa { for (;;) { - nLastRead = maInflater.doInflateSegment( aData, nRead, aData.getLength() - nRead ); + nLastRead = maInflater->doInflateSegment( aData, nRead, aData.getLength() - nRead ); if ( 0 != nLastRead && ( nRead + nLastRead == nRequestedBytes || mnZipCurrent >= mnZipEnd ) ) break; nRead += nLastRead; @@ -239,10 +239,10 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa throw RuntimeException( u"Should not be possible to read more than requested!"_ustr ); - if ( maInflater.finished() || maInflater.getLastInflateError() ) + if ( maInflater->finished() || maInflater->getLastInflateError() ) throw ZipIOException(u"The stream seems to be broken!"_ustr ); - if ( maInflater.needsDictionary() ) + if ( maInflater->needsDictionary() ) throw ZipIOException(u"Dictionaries are not supported!"_ustr ); sal_Int32 nDiff = static_cast< sal_Int32 >( mnZipEnd - mnZipCurrent ); @@ -283,7 +283,7 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa } } } - maInflater.setInput ( maCompBuffer ); + maInflater->setInput ( maCompBuffer ); } } diff --git a/package/source/zipapi/XUnbufferedStream.hxx b/package/source/zipapi/XUnbufferedStream.hxx index f3efe0aaecce..27c6ebc3a841 100644 --- a/package/source/zipapi/XUnbufferedStream.hxx +++ b/package/source/zipapi/XUnbufferedStream.hxx @@ -29,6 +29,7 @@ #include <cppuhelper/implbase.hxx> #include <rtl/ref.hxx> #include <package/Inflater.hxx> +#include <memory> #include <ZipEntry.hxx> #include <CRC32.hxx> @@ -54,7 +55,7 @@ class XUnbufferedStream final : public cppu::WeakImplHelper ZipEntry maEntry; sal_Int32 mnBlockSize; css::uno::Reference< css::xml::crypto::XCipherContext > m_xCipherContext; - ZipUtils::Inflater maInflater; + std::unique_ptr<ZipUtils::Inflater> maInflater; bool mbRawStream, mbWrappedRaw; sal_Int16 mnHeaderToRead; sal_Int64 mnZipCurrent, mnZipEnd, mnZipSize, mnMyCurrent; diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index 5ae674d7272f..fb304b8beaae 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -61,6 +61,8 @@ #include "MemoryByteGrabber.hxx" #include <CRC32.hxx> +#include <package/InflateZlib.hxx> +#include <InflaterBytesZlib.hxx> using namespace com::sun::star; using namespace com::sun::star::io; @@ -88,7 +90,7 @@ ZipFile::ZipFile( rtl::Reference< comphelper::RefCountedMutex > aMutexHolder, : m_aMutexHolder(std::move( aMutexHolder )) , m_Checks(checks) , aGrabber( xInput ) -, aInflater( true ) +, aInflater( std::make_unique<ZipUtils::InflateZlib>(true) ) , xStream(xInput) , m_xContext (std::move( xContext )) , bRecoveryMode( bForceRecovery ) @@ -1959,7 +1961,7 @@ void ZipFile::getSizeAndCRC( sal_Int64 nOffset, sal_Int64 nCompressedSize, sal_I CRC32 aCRC; sal_Int64 nRealSize = 0; - ZipUtils::InflaterBytes aInflaterLocal; + ZipUtils::InflaterBytesZlib aInflaterLocal; sal_Int32 nBlockSize = static_cast< sal_Int32 > (::std::min( nCompressedSize, static_cast< sal_Int64 >( 32000 ) ) ); std::vector < sal_Int8 > aBuffer(nBlockSize); std::vector< sal_Int8 > aData( nBlockSize ); @@ -1981,7 +1983,7 @@ void ZipFile::getSizeAndCRC( sal_Int64 nOffset, sal_Int64 nCompressedSize, sal_I nLastInflated = aInflaterLocal.doInflateSegment( aData.data(), nBlockSize, 0, nBlockSize ); aCRC.updateSegment( aData.data(), nLastInflated ); nInBlock += nLastInflated; - } while( !aInflater.finished() && nLastInflated ); + } while( !aInflaterLocal.finished() && nLastInflated ); nRealSize += nInBlock; } diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist index 76cb39ca577c..1e4a8301319b 100644 --- a/solenv/clang-format/excludelist +++ b/solenv/clang-format/excludelist @@ -5330,6 +5330,7 @@ include/osl/thread.hxx include/osl/time.h include/package/Deflater.hxx include/package/Inflater.hxx +include/package/InflateZlib.hxx include/registry/reader.hxx include/registry/registry.hxx include/registry/typereg_reader.hxx @@ -7065,6 +7066,7 @@ package/inc/ByteGrabber.hxx package/inc/CRC32.hxx package/inc/EncryptionData.hxx package/inc/HashMaps.hxx +package/inc/InflaterBytesZlib.hxx package/inc/ZipFile.hxx package/inc/ZipOutputEntry.hxx package/inc/ZipOutputStream.hxx @@ -7112,6 +7114,8 @@ package/source/zipapi/XBufferedThreadedStream.hxx package/source/zipapi/XUnbufferedStream.cxx package/source/zipapi/XUnbufferedStream.hxx package/source/zipapi/ZipFile.cxx +package/source/zipapi/InflateZlib.cxx +package/source/zipapi/InflaterBytesZlib.cxx package/source/zipapi/ZipOutputEntry.cxx package/source/zipapi/ZipOutputStream.cxx package/source/zipapi/blowfishcontext.cxx