Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/ole/axbinaryreader.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <oox/ole/axbinaryreader.hxx>
21
22
#include <oox/ole/axfontdata.hxx>
23
#include <oox/ole/olehelper.hxx>
24
25
#include <osl/diagnose.h>
26
27
namespace oox::ole {
28
29
namespace {
30
31
const sal_uInt32 AX_STRING_SIZEMASK         = 0x7FFFFFFF;
32
const sal_uInt32 AX_STRING_COMPRESSED       = 0x80000000;
33
34
} // namespace
35
36
AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream& rInStrm ) :
37
36
    BinaryStreamBase( false ),
38
36
    mpInStrm( &rInStrm ),
39
36
    mnStrmPos( 0 ),
40
36
    mnStrmSize( rInStrm.getRemaining() )
41
36
{
42
36
    mbEof = mbEof || rInStrm.isEof();
43
36
}
Unexecuted instantiation: oox::ole::AxAlignedInputStream::AxAlignedInputStream(oox::BinaryInputStream&)
oox::ole::AxAlignedInputStream::AxAlignedInputStream(oox::BinaryInputStream&)
Line
Count
Source
37
36
    BinaryStreamBase( false ),
38
36
    mpInStrm( &rInStrm ),
39
36
    mnStrmPos( 0 ),
40
36
    mnStrmSize( rInStrm.getRemaining() )
41
36
{
42
36
    mbEof = mbEof || rInStrm.isEof();
43
36
}
44
45
sal_Int64 AxAlignedInputStream::size() const
46
0
{
47
0
    return mpInStrm ? mnStrmSize : -1;
48
0
}
49
50
sal_Int64 AxAlignedInputStream::tell() const
51
72
{
52
72
    return mpInStrm ? mnStrmPos : -1;
53
72
}
54
55
void AxAlignedInputStream::seek( sal_Int64 nPos )
56
72
{
57
72
    mbEof = mbEof || (nPos < mnStrmPos);
58
72
    if( !mbEof )
59
72
        skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) );
60
72
}
61
62
void AxAlignedInputStream::close()
63
0
{
64
0
    mpInStrm = nullptr;
65
0
    mbEof = true;
66
0
}
67
68
sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
69
0
{
70
0
    sal_Int32 nReadSize = 0;
71
0
    if( !mbEof )
72
0
    {
73
0
        nReadSize = mpInStrm->readData( orData, nBytes, nAtomSize );
74
0
        mnStrmPos += nReadSize;
75
0
        mbEof = mpInStrm->isEof();
76
0
    }
77
0
    return nReadSize;
78
0
}
79
80
sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
81
242
{
82
242
    sal_Int32 nReadSize = 0;
83
242
    if( !mbEof )
84
242
    {
85
242
        nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize );
86
242
        mnStrmPos += nReadSize;
87
242
        mbEof = mpInStrm->isEof();
88
242
    }
89
242
    return nReadSize;
90
242
}
91
92
void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
93
348
{
94
348
    if( !mbEof )
95
348
    {
96
348
        mpInStrm->skip( nBytes, nAtomSize );
97
348
        mnStrmPos += nBytes;
98
348
        mbEof = mpInStrm->isEof();
99
348
    }
100
348
}
101
102
void AxAlignedInputStream::align( size_t nSize )
103
214
{
104
214
    skip( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
105
214
}
106
107
namespace {
108
109
bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
110
36
{
111
36
    bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
112
36
    sal_uInt32 nBufSize = nSize & AX_STRING_SIZEMASK;
113
    // Unicode: simple strings store byte count, array strings store char count
114
36
    sal_Int32 nChars = static_cast< sal_Int32 >( nBufSize / ((bCompressed || bArrayString) ? 1 : 2) );
115
36
    bool bValidChars = nChars <= 65536;
116
36
    OSL_ENSURE( bValidChars, "lclReadString - string too long" );
117
36
    sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2);
118
36
    nChars = ::std::min< sal_Int32 >( nChars, 65536 );
119
36
    rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed );
120
36
    rInStrm.seek( nEndPos );
121
36
    return bValidChars;
122
36
}
123
124
} // namespace
125
126
AxBinaryPropertyReader::ComplexProperty::~ComplexProperty()
127
54
{
128
54
}
129
130
bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream& rInStrm )
131
18
{
132
18
    mrPairData.first = rInStrm.readInt32();
133
18
    mrPairData.second = rInStrm.readInt32();
134
18
    return true;
135
18
}
136
137
bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream& rInStrm )
138
36
{
139
36
    return lclReadString( rInStrm, mrValue, mnSize, false );
140
36
}
141
142
bool AxBinaryPropertyReader::ArrayStringProperty::readProperty( AxAlignedInputStream& rInStrm )
143
0
{
144
0
    sal_Int64 nEndPos = rInStrm.tell() + mnSize;
145
0
    while( rInStrm.tell() < nEndPos )
146
0
    {
147
0
        OUString aString;
148
0
        if( !lclReadString( rInStrm, aString, rInStrm.readuInt32(), true ) )
149
0
            return false;
150
0
        mrArray.push_back( aString );
151
        // every array string is aligned on 4 byte boundaries
152
0
        rInStrm.align( 4 );
153
0
    }
154
0
    return true;
155
0
}
156
157
bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream& rInStrm )
158
0
{
159
0
    mrGuid = OleHelper::importGuid( rInStrm );
160
0
    return true;
161
0
}
162
163
bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream& rInStrm )
164
0
{
165
0
    return mrFontData.importGuidAndFont( rInStrm );
166
0
}
167
168
bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream& rInStrm )
169
0
{
170
0
    return OleHelper::importStdPic( mrPicData, rInStrm );
171
0
}
172
173
AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream& rInStrm, bool b64BitPropFlags ) :
174
36
    maInStrm( rInStrm ),
175
36
    mbValid( true )
176
36
{
177
    // version and size of property block
178
36
    maInStrm.skip( 2 );
179
36
    sal_uInt16 nBlockSize = maInStrm.readuInt16();
180
36
    mnPropsEnd = maInStrm.tell() + nBlockSize;
181
    // flagfield containing existing properties
182
36
    if( b64BitPropFlags )
183
8
        mnPropFlags = maInStrm.readInt64();
184
28
    else
185
28
        mnPropFlags = maInStrm.readuInt32();
186
36
    mnNextProp = 1;
187
36
}
188
189
void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse )
190
10
{
191
    // there is no data, the boolean value is equivalent to the property flag itself
192
10
    orbValue = startNextProperty() != bReverse;
193
10
}
194
195
void AxBinaryPropertyReader::readPairProperty( AxPairData& orPairData )
196
18
{
197
18
    if( startNextProperty() )
198
18
        maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<PairProperty>( orPairData ) ) );
199
18
}
200
201
void AxBinaryPropertyReader::readStringProperty( OUString& orValue )
202
52
{
203
52
    if( startNextProperty() )
204
36
    {
205
36
        sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
206
36
        maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<StringProperty>( orValue, nSize ) ) );
207
36
    }
208
52
}
209
210
void AxBinaryPropertyReader::readArrayStringProperty( std::vector<OUString>& orValue )
211
0
{
212
0
    if( startNextProperty() )
213
0
    {
214
0
        sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
215
0
        maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<ArrayStringProperty>( orValue, nSize ) ) );
216
0
    }
217
0
}
218
219
void AxBinaryPropertyReader::readGuidProperty( OUString& orGuid )
220
0
{
221
0
    if( startNextProperty() )
222
0
        maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<GuidProperty>( orGuid ) ) );
223
0
}
224
225
void AxBinaryPropertyReader::readFontProperty( AxFontData& orFontData )
226
0
{
227
0
    if( startNextProperty() )
228
0
    {
229
0
        sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
230
0
        if( ensureValid( nData == -1 ) )
231
0
            maStreamProps.push_back( ComplexPropVector::value_type( std::make_shared<FontProperty>( orFontData ) ) );
232
0
    }
233
0
}
234
235
void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence& orPicData )
236
36
{
237
36
    if( startNextProperty() )
238
0
    {
239
0
        sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
240
0
        if( ensureValid( nData == -1 ) )
241
0
            maStreamProps.push_back( ComplexPropVector::value_type( std::make_shared<PictureProperty>( orPicData ) ) );
242
0
    }
243
36
}
244
245
bool AxBinaryPropertyReader::finalizeImport()
246
36
{
247
    // read large properties
248
36
    maInStrm.align( 4 );
249
36
    if( ensureValid( mnPropFlags == 0 ) )
250
36
    {
251
36
        for (auto const& largeProp : maLargeProps)
252
54
        {
253
54
            if (!ensureValid())
254
0
                break;
255
54
            ensureValid( largeProp->readProperty( maInStrm ) );
256
54
            maInStrm.align( 4 );
257
54
        }
258
36
    }
259
36
    maInStrm.seek( mnPropsEnd );
260
261
    // read stream properties (no stream alignment between properties!)
262
36
    if( ensureValid() )
263
36
    {
264
36
        for (auto const& streamProp : maStreamProps)
265
0
        {
266
0
            if (!ensureValid())
267
0
                break;
268
0
            ensureValid( streamProp->readProperty( maInStrm ) );
269
0
        }
270
36
    }
271
272
36
    return mbValid;
273
36
}
274
275
bool AxBinaryPropertyReader::ensureValid( bool bCondition )
276
714
{
277
714
    mbValid = mbValid && bCondition && !maInStrm.isEof();
278
714
    return mbValid;
279
714
}
280
281
bool AxBinaryPropertyReader::startNextProperty()
282
518
{
283
518
    bool bHasProp = getFlag( mnPropFlags, mnNextProp );
284
518
    setFlag( mnPropFlags, mnNextProp, false );
285
518
    mnNextProp <<= 1;
286
518
    return ensureValid() && bHasProp;
287
518
}
288
289
} // namespace oox::ole
290
291
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */