Coverage Report

Created: 2026-03-12 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwpd/src/lib/WP1VariableLengthGroup.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* libwpd
3
 * Version: MPL 2.0 / LGPLv2.1+
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
 * Major Contributor(s):
10
 * Copyright (C) 2003 William Lachance (wrlach@gmail.com)
11
 * Copyright (C) 2003 Marc Maurer (uwog@uwog.net)
12
 * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch)
13
 *
14
 * For minor contributions see the git repository.
15
 *
16
 * Alternatively, the contents of this file may be used under the terms
17
 * of the GNU Lesser General Public License Version 2.1 or later
18
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
19
 * applicable instead of those above.
20
 *
21
 * For further information visit http://libwpd.sourceforge.net
22
 */
23
24
/* "This product is not manufactured, approved, or supported by
25
 * Corel Corporation or Corel Corporation Limited."
26
 */
27
28
#include "WP1VariableLengthGroup.h"
29
#include "WP1UnsupportedVariableLengthGroup.h"
30
#include "WP1SetTabsGroup.h"
31
#include "WP1HeaderFooterGroup.h"
32
#include "WP1FootnoteEndnoteGroup.h"
33
#include "WP1PictureGroup.h"
34
#include "WP1FileStructure.h"
35
#include "libwpd_internal.h"
36
#include <limits>
37
38
WP1VariableLengthGroup::WP1VariableLengthGroup(unsigned char group) :
39
97.7k
  m_group(group),
40
97.7k
  m_size(0)
41
97.7k
{
42
97.7k
}
43
44
WP1VariableLengthGroup *WP1VariableLengthGroup::constructVariableLengthGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption, unsigned char group)
45
97.7k
{
46
97.7k
  switch (group)
47
97.7k
  {
48
5.53k
  case WP1_SET_TABS_GROUP:
49
5.53k
    return new WP1SetTabsGroup(input, encryption, group);
50
8.28k
  case WP1_HEADER_FOOTER_GROUP:
51
8.28k
    return new WP1HeaderFooterGroup(input, encryption, group);
52
1.91k
  case WP1_FOOTNOTE_ENDNOTE_GROUP:
53
1.91k
    return new WP1FootnoteEndnoteGroup(input, encryption, group);
54
81.5k
  case WP1_PICTURE_GROUP:
55
81.5k
    return new WP1PictureGroup(input, encryption, group);
56
448
  default:
57
    // this is an unhandled group, just skip it
58
448
    return new WP1UnsupportedVariableLengthGroup(input, encryption, group);
59
97.7k
  }
60
97.7k
}
61
62
bool WP1VariableLengthGroup::isGroupConsistent(librevenge::RVNGInputStream *input, WPXEncryption *encryption, const unsigned char group)
63
145k
{
64
145k
  long startPosition = input->tell();
65
145k
  if (startPosition < 0)
66
0
    throw FileException();
67
68
145k
  try
69
145k
  {
70
145k
    unsigned size = readU32(input, encryption, true);
71
145k
    if (size > ((std::numeric_limits<unsigned>::max)() / 2))
72
14.0k
      return false;
73
74
130k
    if (input->seek(size, librevenge::RVNG_SEEK_CUR) || input->isEnd())
75
18.1k
    {
76
18.1k
      input->seek(startPosition, librevenge::RVNG_SEEK_SET);
77
18.1k
      return false;
78
18.1k
    }
79
112k
    if (size != readU32(input, encryption, true))
80
5.23k
    {
81
5.23k
      input->seek(startPosition, librevenge::RVNG_SEEK_SET);
82
5.23k
      return false;
83
5.23k
    }
84
107k
    if (group != readU8(input, encryption))
85
527
    {
86
527
      input->seek(startPosition, librevenge::RVNG_SEEK_SET);
87
527
      return false;
88
527
    }
89
90
107k
    input->seek(startPosition, librevenge::RVNG_SEEK_SET);
91
107k
    return true;
92
107k
  }
93
145k
  catch (...)
94
145k
  {
95
9.28k
    input->seek(startPosition, librevenge::RVNG_SEEK_SET);
96
9.28k
    return false;
97
9.28k
  }
98
145k
}
99
100
void WP1VariableLengthGroup::_read(librevenge::RVNGInputStream *input, WPXEncryption *encryption)
101
97.7k
{
102
97.7k
  long startPosition = input->tell();
103
97.7k
  if (startPosition < 0)
104
0
    throw FileException();
105
106
97.7k
  WPD_DEBUG_MSG(("WordPerfect: handling a variable length group\n"));
107
108
97.7k
  m_size = readU32(input, encryption, true); // the length is the number of data bytes minus 4 (ie. the function codes)
109
110
97.7k
  if ((long)(m_size + startPosition) < startPosition)
111
0
    throw FileException();
112
113
97.7k
  WPD_DEBUG_MSG(("WordPerfect: Read variable group header (start_position: %li, size: %u)\n", startPosition, m_size));
114
115
97.7k
  _readContents(input, encryption);
116
117
97.7k
  if ((m_size + (unsigned long)startPosition + 4 < m_size + (unsigned long)startPosition) ||
118
97.6k
          (m_size + (unsigned long)startPosition + 4) > ((std::numeric_limits<unsigned>::max)() / 2))
119
0
    throw FileException();
120
121
97.7k
  input->seek(startPosition + m_size + 4, librevenge::RVNG_SEEK_SET);
122
123
97.7k
  if (m_size != readU32(input, encryption, true))
124
0
  {
125
0
    WPD_DEBUG_MSG(("WordPerfect: Possible corruption detected. Bailing out!\n"));
126
0
    throw FileException();
127
0
  }
128
97.7k
  if (m_group != readU8(input, encryption))
129
0
  {
130
0
    WPD_DEBUG_MSG(("WordPerfect: Possible corruption detected. Bailing out!\n"));
131
0
    throw FileException();
132
0
  }
133
134
97.7k
  if ((m_size + (unsigned long)startPosition + 9 < m_size + (unsigned long)startPosition) ||
135
97.6k
          (m_size + (unsigned long)startPosition + 9) > ((std::numeric_limits<unsigned>::max)() / 2))
136
0
    throw FileException();
137
97.7k
  input->seek(startPosition + m_size + 9, librevenge::RVNG_SEEK_SET);
138
139
97.7k
}
140
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */