cid#1636690 Dereference after null check
[LibreOffice.git] / oox / source / ole / axbinarywriter.cxx
blobb9c4b66bec729d1897312590a2b9c2f04fd55926
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9 #include <oox/ole/axbinarywriter.hxx>
11 namespace oox::ole {
13 namespace {
15 const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000;
17 } // namespace
19 AxAlignedOutputStream::AxAlignedOutputStream( BinaryOutputStream& rOutStrm ) :
20 BinaryStreamBase( false ),
21 mpOutStrm( &rOutStrm ),
22 mnStrmPos( 0 ),
23 mnStrmSize( rOutStrm.getRemaining() ),
24 mnWrappedBeginPos( rOutStrm.tell() )
26 mbEof = mbEof || rOutStrm.isEof();
29 sal_Int64 AxAlignedOutputStream::size() const
31 return mpOutStrm ? mnStrmSize : -1;
34 sal_Int64 AxAlignedOutputStream::tell() const
36 return mpOutStrm ? mnStrmPos : -1;
39 void AxAlignedOutputStream::seek( sal_Int64 nPos )
41 mbEof = (nPos < 0);
42 if( !mbEof )
44 mpOutStrm->seek( static_cast< sal_Int32 >( mnWrappedBeginPos + nPos ) );
45 mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
49 void AxAlignedOutputStream::close()
51 mpOutStrm = nullptr;
52 mbEof = true;
55 void AxAlignedOutputStream::writeData( const StreamDataSequence& orData, size_t nAtomSize )
57 mpOutStrm->writeData( orData, nAtomSize );
58 mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
61 void AxAlignedOutputStream::writeMemory( const void* opMem, sal_Int32 nBytes, size_t nAtomSize )
63 mpOutStrm->writeMemory( opMem, nBytes, nAtomSize );
64 mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
67 void AxAlignedOutputStream::pad( sal_Int32 nBytes )
69 //PRESUMABLY we need to pad with 0's here as appropriate
70 css::uno::Sequence< sal_Int8 > aData( nBytes );
71 // ok we could be padding with rubbish here, but really that shouldn't matter
72 // set to 0(s), easier to not get fooled by 0's when looking at
73 // binary content...
74 memset( static_cast<void*>( aData.getArray() ), 0, nBytes );
75 mpOutStrm->writeData( aData );
76 mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
79 void AxAlignedOutputStream::align( size_t nSize )
81 pad( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
84 namespace {
86 void lclWriteString( AxAlignedOutputStream& rOutStrm, OUString const & rValue, sal_uInt32 nSize )
88 bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
89 rOutStrm.writeCompressedUnicodeArray( rValue, bCompressed );
92 } // namespace
94 AxBinaryPropertyWriter::ComplexProperty::~ComplexProperty()
98 bool AxBinaryPropertyWriter::PairProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
100 rOutStrm.WriteInt32(mrPairData.first).WriteInt32(mrPairData.second);
101 return true;
104 bool AxBinaryPropertyWriter::StringProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
106 lclWriteString( rOutStrm, mrValue, mnSize );
107 return true;
110 AxBinaryPropertyWriter::AxBinaryPropertyWriter( BinaryOutputStream& rOutStrm, bool b64BitPropFlags ) :
111 maOutStrm( rOutStrm ),
112 mnPropFlags( 0x0 ),
113 mbValid( true ),
114 mb64BitPropFlags( b64BitPropFlags )
116 sal_uInt16 nId( 0x0200 );
117 maOutStrm.WriteUInt16(nId);
118 mnBlockSize = 0; // will be filled in the finalize method
120 maOutStrm.WriteUInt16(nId);
121 mnPropFlagsStart = maOutStrm.tell();
123 if( mb64BitPropFlags )
124 maOutStrm.WriteInt64( mnPropFlags );
125 else
126 maOutStrm.WriteUInt32( mnPropFlags );
127 mnNextProp = 1;
130 void AxBinaryPropertyWriter::writeBoolProperty( bool orbValue )
132 // orbValue == bReverse false then we want to set the bit, e.g. don't skip
133 startNextProperty( !orbValue );
136 void AxBinaryPropertyWriter::writePairProperty( AxPairData& orPairData )
138 startNextProperty();
139 maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<PairProperty>( orPairData ) ) );
142 void AxBinaryPropertyWriter::writeStringProperty( OUString& orValue )
144 sal_uInt32 nSize = orValue.getLength() * 2;
145 setFlag( nSize, AX_STRING_COMPRESSED, false );
146 maOutStrm.writeAligned< sal_uInt32 >( nSize );
147 maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<StringProperty>( orValue, nSize ) ) );
148 startNextProperty();
151 void AxBinaryPropertyWriter::finalizeExport()
153 // write large properties
154 maOutStrm.align( 4 );
155 for (auto const& largeProp : maLargeProps)
157 if (!ensureValid())
158 break;
159 largeProp->writeProperty( maOutStrm );
160 maOutStrm.align( 4 );
163 mnBlockSize = maOutStrm.tell() - mnPropFlagsStart;
165 // write stream properties (no stream alignment between properties!)
166 for (auto const& streamProp : maStreamProps)
168 if (!ensureValid())
169 break;
170 streamProp->writeProperty( maOutStrm );
173 sal_Int64 nPos = maOutStrm.tell();
174 maOutStrm.seek( mnPropFlagsStart - sizeof( mnBlockSize ) );
176 maOutStrm.WriteInt16( mnBlockSize );
178 if( mb64BitPropFlags )
179 maOutStrm.WriteInt64( mnPropFlags );
180 else
181 maOutStrm.WriteUInt32( mnPropFlags );
183 maOutStrm.seek( nPos );
186 bool AxBinaryPropertyWriter::ensureValid()
188 mbValid = mbValid && !maOutStrm.isEof();
189 return mbValid;
192 void AxBinaryPropertyWriter::startNextProperty( bool bSkip )
194 // if we are skipping then we clear the flag
195 setFlag( mnPropFlags, mnNextProp, !bSkip );
196 mnNextProp <<= 1;
199 } // namespace oox::ole
201 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */