io/source/TextInputStream/TextInputStream.cxx | 53 ++++++++++----------- io/source/TextOutputStream/TextOutputStream.cxx | 58 ++++++++++-------------- 2 files changed, 50 insertions(+), 61 deletions(-)
New commits: commit 8985041da5359892e627922fc64cfe70dcc2ca57 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri Aug 22 13:30:36 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Aug 22 18:40:40 2025 +0200 Throw from OText{Input,Output}Stream::setEncoding on unknown encoding Before this, it was possible to pass an arbitrary string to the method, and have no way of knowing about the problem. IllegalArgumentException is derived from RuntimeException, which is explicitly documented to be allowed at every interface method, signalling errors not covered by the interface method specification, so this is not an API change. Change-Id: I038f7765ec3f332f0e787351fa032feeef2cefb0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190048 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins diff --git a/io/source/TextInputStream/TextInputStream.cxx b/io/source/TextInputStream/TextInputStream.cxx index 9edf80dcc0e7..c00c04c7cc74 100644 --- a/io/source/TextInputStream/TextInputStream.cxx +++ b/io/source/TextInputStream/TextInputStream.cxx @@ -30,6 +30,7 @@ #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/io/NotConnectedException.hpp> #include <com/sun/star/io/XTextInputStream2.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <optional> @@ -165,8 +166,6 @@ OUString OTextInputStream::implReadString( const Sequence< sal_Unicode >& Delimi { setEncoding( u"utf8"_ustr ); } - if (!moEncoding) - return aRetStr; // Only for bFindLineEnd constexpr sal_Unicode cLineEndChar1 = ' '; @@ -310,7 +309,7 @@ void OTextInputStream::setEncoding( const OUString& Encoding ) OString aOEncodingStr = OUStringToOString( Encoding, RTL_TEXTENCODING_ASCII_US ); rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( aOEncodingStr.getStr() ); if( RTL_TEXTENCODING_DONTKNOW == encoding ) - return; + throw IllegalArgumentException("Unknown encoding '" + Encoding + "'", getXWeak(), 0); moEncoding.emplace(encoding); } diff --git a/io/source/TextOutputStream/TextOutputStream.cxx b/io/source/TextOutputStream/TextOutputStream.cxx index 6790c3ae231c..893db57fe52a 100644 --- a/io/source/TextOutputStream/TextOutputStream.cxx +++ b/io/source/TextOutputStream/TextOutputStream.cxx @@ -27,6 +27,7 @@ #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/io/XTextOutputStream2.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <optional> @@ -147,8 +148,6 @@ void OTextOutputStream::writeString( const OUString& aString ) { setEncoding( u"utf8"_ustr ); } - if (!moEncoding) - return; Sequence<sal_Int8> aByteSeq = implConvert( aString ); mxStream->writeBytes( aByteSeq ); @@ -159,7 +158,7 @@ void OTextOutputStream::setEncoding( const OUString& Encoding ) OString aOEncodingStr = OUStringToOString( Encoding, RTL_TEXTENCODING_ASCII_US ); rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( aOEncodingStr.getStr() ); if( RTL_TEXTENCODING_DONTKNOW == encoding ) - return; + throw IllegalArgumentException("Unknown encoding '" + Encoding + "'", getXWeak(), 0); moEncoding.emplace(encoding); } commit ec4628b7976a2840eebe38da3fe2bddb1d6b1573 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri Aug 22 13:07:26 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Aug 22 18:40:35 2025 +0200 Avoid memory leak in OText{Input,Output}Stream::setEncoding These classes used to only destroy their converter and context in dtor; but their setEncoding API method can be called several times, and every time after the initial initialization, it leaked active converter and context. Change-Id: Ie71cf73e4bc36a94b433898bc6bb3041dab700e7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190047 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins diff --git a/io/source/TextInputStream/TextInputStream.cxx b/io/source/TextInputStream/TextInputStream.cxx index 287783ca3fad..9edf80dcc0e7 100644 --- a/io/source/TextInputStream/TextInputStream.cxx +++ b/io/source/TextInputStream/TextInputStream.cxx @@ -32,6 +32,7 @@ #include <com/sun/star/io/XTextInputStream2.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> +#include <optional> #include <vector> namespace com::sun::star::uno { class XComponentContext; } @@ -53,10 +54,22 @@ class OTextInputStream : public WeakImplHelper< XTextInputStream2, XServiceInfo { Reference< XInputStream > mxStream; - // Encoding - bool mbEncodingInitialized; - rtl_TextToUnicodeConverter mConvText2Unicode; - rtl_TextToUnicodeContext mContextText2Unicode; + struct Encoding_t + { + rtl_TextToUnicodeConverter mConvText2Unicode; + rtl_TextToUnicodeContext mContextText2Unicode; + Encoding_t(rtl_TextEncoding encoding) + { + mConvText2Unicode = rtl_createTextToUnicodeConverter(encoding); + mContextText2Unicode = rtl_createTextToUnicodeContext(mConvText2Unicode); + } + ~Encoding_t() + { + rtl_destroyTextToUnicodeContext(mConvText2Unicode, mContextText2Unicode); + rtl_destroyTextToUnicodeConverter(mConvText2Unicode); + } + }; + std::optional<Encoding_t> moEncoding; Sequence<sal_Int8> mSeqSource; // Internal buffer for characters that are already converted successfully @@ -76,7 +89,6 @@ class OTextInputStream : public WeakImplHelper< XTextInputStream2, XServiceInfo public: OTextInputStream(); - virtual ~OTextInputStream() override; // Methods XTextInputStream virtual OUString SAL_CALL readLine( ) override; @@ -104,25 +116,13 @@ public: } OTextInputStream::OTextInputStream() - : mbEncodingInitialized(false) - , mConvText2Unicode(nullptr) - , mContextText2Unicode(nullptr) - , mSeqSource(READ_BYTE_COUNT) + : mSeqSource(READ_BYTE_COUNT) , mvBuffer(INITIAL_UNICODE_BUFFER_CAPACITY, 0) , mnCharsInBuffer(0) , mbReachedEOF(false) { } -OTextInputStream::~OTextInputStream() -{ - if( mbEncodingInitialized ) - { - rtl_destroyTextToUnicodeContext( mConvText2Unicode, mContextText2Unicode ); - rtl_destroyTextToUnicodeConverter( mConvText2Unicode ); - } -} - // Check uninitialized object void OTextInputStream::checkNull() @@ -161,11 +161,11 @@ OUString OTextInputStream::implReadString( const Sequence< sal_Unicode >& Delimi bool bRemoveDelimiter, bool bFindLineEnd ) { OUString aRetStr; - if( !mbEncodingInitialized ) + if (!moEncoding) { setEncoding( u"utf8"_ustr ); } - if( !mbEncodingInitialized ) + if (!moEncoding) return aRetStr; // Only for bFindLineEnd @@ -265,8 +265,8 @@ sal_Int32 OTextInputStream::implReadNext() // All invalid characters are transformed to the unicode undefined char sal_Size nSrcCvtBytes = 0; mnCharsInBuffer += rtl_convertTextToUnicode( - mConvText2Unicode, - mContextText2Unicode, + moEncoding->mConvText2Unicode, + moEncoding->mContextText2Unicode, reinterpret_cast<const char*>(mSeqSource.getConstArray() + nSourceCount), mSeqSource.getLength() - nSourceCount, mvBuffer.data() + mnCharsInBuffer, @@ -312,9 +312,7 @@ void OTextInputStream::setEncoding( const OUString& Encoding ) if( RTL_TEXTENCODING_DONTKNOW == encoding ) return; - mbEncodingInitialized = true; - mConvText2Unicode = rtl_createTextToUnicodeConverter( encoding ); - mContextText2Unicode = rtl_createTextToUnicodeContext( mConvText2Unicode ); + moEncoding.emplace(encoding); } @@ -382,7 +380,7 @@ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* io_OTextInputStream_get_implementation( css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&) { - return cppu::acquire(new OTextInputStream()); + return cppu::acquire(new OTextInputStream); } diff --git a/io/source/TextOutputStream/TextOutputStream.cxx b/io/source/TextOutputStream/TextOutputStream.cxx index f576b9881672..6790c3ae231c 100644 --- a/io/source/TextOutputStream/TextOutputStream.cxx +++ b/io/source/TextOutputStream/TextOutputStream.cxx @@ -29,6 +29,8 @@ #include <com/sun/star/io/XTextOutputStream2.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> +#include <optional> + namespace com::sun::star::uno { class XComponentContext; } using namespace ::cppu; @@ -44,19 +46,28 @@ class OTextOutputStream : public WeakImplHelper< XTextOutputStream2, XServiceInf { Reference< XOutputStream > mxStream; - // Encoding - bool mbEncodingInitialized; - rtl_UnicodeToTextConverter mConvUnicode2Text; - rtl_UnicodeToTextContext mContextUnicode2Text; + struct Encoding_t + { + rtl_UnicodeToTextConverter mConvUnicode2Text; + rtl_UnicodeToTextContext mContextUnicode2Text; + Encoding_t(rtl_TextEncoding encoding) + { + mConvUnicode2Text = rtl_createUnicodeToTextConverter(encoding); + mContextUnicode2Text = rtl_createUnicodeToTextContext(mConvUnicode2Text); + } + ~Encoding_t() + { + rtl_destroyUnicodeToTextContext(mConvUnicode2Text, mContextUnicode2Text); + rtl_destroyUnicodeToTextConverter(mConvUnicode2Text); + } + }; + std::optional<Encoding_t> moEncoding; Sequence<sal_Int8> implConvert( const OUString& rSource ); /// @throws IOException void checkOutputStream() const; public: - OTextOutputStream(); - virtual ~OTextOutputStream() override; - // Methods XTextOutputStream virtual void SAL_CALL writeString( const OUString& aString ) override; virtual void SAL_CALL setEncoding( const OUString& Encoding ) override; @@ -78,22 +89,6 @@ public: } -OTextOutputStream::OTextOutputStream() - : mbEncodingInitialized(false) - , mConvUnicode2Text(nullptr) - , mContextUnicode2Text(nullptr) -{ -} - -OTextOutputStream::~OTextOutputStream() -{ - if( mbEncodingInitialized ) - { - rtl_destroyUnicodeToTextContext( mConvUnicode2Text, mContextUnicode2Text ); - rtl_destroyUnicodeToTextConverter( mConvUnicode2Text ); - } -} - Sequence<sal_Int8> OTextOutputStream::implConvert( const OUString& rSource ) { const sal_Unicode *puSource = rSource.getStr(); @@ -115,8 +110,8 @@ Sequence<sal_Int8> OTextOutputStream::implConvert( const OUString& rSource ) while( true ) { nTargetCount += rtl_convertUnicodeToText( - mConvUnicode2Text, - mContextUnicode2Text, + moEncoding->mConvUnicode2Text, + moEncoding->mContextUnicode2Text, &( puSource[nSourceCount] ), nSourceSize - nSourceCount , &( pTarget[nTargetCount] ), @@ -148,11 +143,11 @@ Sequence<sal_Int8> OTextOutputStream::implConvert( const OUString& rSource ) void OTextOutputStream::writeString( const OUString& aString ) { checkOutputStream(); - if( !mbEncodingInitialized ) + if (!moEncoding) { setEncoding( u"utf8"_ustr ); } - if( !mbEncodingInitialized ) + if (!moEncoding) return; Sequence<sal_Int8> aByteSeq = implConvert( aString ); @@ -166,9 +161,7 @@ void OTextOutputStream::setEncoding( const OUString& Encoding ) if( RTL_TEXTENCODING_DONTKNOW == encoding ) return; - mbEncodingInitialized = true; - mConvUnicode2Text = rtl_createUnicodeToTextConverter( encoding ); - mContextUnicode2Text = rtl_createUnicodeToTextContext( mConvUnicode2Text ); + moEncoding.emplace(encoding); } @@ -232,7 +225,7 @@ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* io_OTextOutputStream_get_implementation( css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&) { - return cppu::acquire(new OTextOutputStream()); + return cppu::acquire(new OTextOutputStream); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */