1 | //======================================================================== |
2 | // |
3 | // FoFiBase.cc |
4 | // |
5 | // Copyright 1999-2003 Glyph & Cog, LLC |
6 | // |
7 | //======================================================================== |
8 | |
9 | //======================================================================== |
10 | // |
11 | // Modified under the Poppler project - http://poppler.freedesktop.org |
12 | // |
13 | // All changes made under the Poppler project to this file are licensed |
14 | // under GPL version 2 or later |
15 | // |
16 | // Copyright (C) 2008 Ed Avis <eda@waniasset.com> |
17 | // Copyright (C) 2011 Jim Meyering <jim@meyering.net> |
18 | // Copyright (C) 2016, 2018, 2020 Albert Astals Cid <aacid@kde.org> |
19 | // Copyright (C) 2019 Christian Persch <chpe@src.gnome.org> |
20 | // Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent@gmail.com> |
21 | // Copyright (C) 2022 Oliver Sander <oliver.sander@tu-dresden.de> |
22 | // |
23 | // To see a description of the changes please see the Changelog file that |
24 | // came with your tarball or type make ChangeLog if you are building from git |
25 | // |
26 | //======================================================================== |
27 | |
28 | #include <config.h> |
29 | |
30 | #include <cstdio> |
31 | #include <climits> |
32 | #include "goo/gfile.h" |
33 | #include "goo/gmem.h" |
34 | #include "poppler/Error.h" |
35 | #include "FoFiBase.h" |
36 | |
37 | //------------------------------------------------------------------------ |
38 | // FoFiBase |
39 | //------------------------------------------------------------------------ |
40 | |
41 | FoFiBase::FoFiBase(const unsigned char *fileA, int lenA, bool freeFileDataA) |
42 | { |
43 | file = fileA; |
44 | len = lenA; |
45 | freeFileData = freeFileDataA; |
46 | } |
47 | |
48 | FoFiBase::~FoFiBase() |
49 | { |
50 | if (freeFileData) { |
51 | gfree(p: (char *)file); |
52 | } |
53 | } |
54 | |
55 | char *FoFiBase::readFile(const char *fileName, int *fileLen) |
56 | { |
57 | FILE *f; |
58 | char *buf; |
59 | int n; |
60 | |
61 | if (!(f = openFile(path: fileName, mode: "rb" ))) { |
62 | error(category: errIO, pos: -1, msg: "Cannot open '{0:s}'" , fileName); |
63 | return nullptr; |
64 | } |
65 | if (fseek(stream: f, off: 0, SEEK_END) != 0) { |
66 | error(category: errIO, pos: -1, msg: "Cannot seek to end of '{0:s}'" , fileName); |
67 | fclose(stream: f); |
68 | return nullptr; |
69 | } |
70 | n = (int)ftell(stream: f); |
71 | if (n < 0) { |
72 | error(category: errIO, pos: -1, msg: "Cannot determine length of '{0:s}'" , fileName); |
73 | fclose(stream: f); |
74 | return nullptr; |
75 | } |
76 | if (fseek(stream: f, off: 0, SEEK_SET) != 0) { |
77 | error(category: errIO, pos: -1, msg: "Cannot seek to start of '{0:s}'" , fileName); |
78 | fclose(stream: f); |
79 | return nullptr; |
80 | } |
81 | buf = (char *)gmalloc(size: n); |
82 | if ((int)fread(ptr: buf, size: 1, n: n, stream: f) != n) { |
83 | gfree(p: buf); |
84 | fclose(stream: f); |
85 | return nullptr; |
86 | } |
87 | fclose(stream: f); |
88 | *fileLen = n; |
89 | return buf; |
90 | } |
91 | |
92 | int FoFiBase::getS8(int pos, bool *ok) const |
93 | { |
94 | int x; |
95 | |
96 | if (pos < 0 || pos >= len) { |
97 | *ok = false; |
98 | return 0; |
99 | } |
100 | x = file[pos]; |
101 | if (x & 0x80) { |
102 | x |= ~0xff; |
103 | } |
104 | return x; |
105 | } |
106 | |
107 | int FoFiBase::getU8(int pos, bool *ok) const |
108 | { |
109 | if (pos < 0 || pos >= len) { |
110 | *ok = false; |
111 | return 0; |
112 | } |
113 | return file[pos]; |
114 | } |
115 | |
116 | int FoFiBase::getS16BE(int pos, bool *ok) const |
117 | { |
118 | int x; |
119 | |
120 | if (pos < 0 || pos > INT_MAX - 1 || pos + 1 >= len) { |
121 | *ok = false; |
122 | return 0; |
123 | } |
124 | x = file[pos]; |
125 | x = (x << 8) + file[pos + 1]; |
126 | if (x & 0x8000) { |
127 | x |= ~0xffff; |
128 | } |
129 | return x; |
130 | } |
131 | |
132 | int FoFiBase::getU16BE(int pos, bool *ok) const |
133 | { |
134 | int x; |
135 | |
136 | if (pos < 0 || pos > INT_MAX - 1 || pos + 1 >= len) { |
137 | *ok = false; |
138 | return 0; |
139 | } |
140 | x = file[pos]; |
141 | x = (x << 8) + file[pos + 1]; |
142 | return x; |
143 | } |
144 | |
145 | int FoFiBase::getS32BE(int pos, bool *ok) const |
146 | { |
147 | int x; |
148 | |
149 | if (pos < 0 || pos > INT_MAX - 3 || pos + 3 >= len) { |
150 | *ok = false; |
151 | return 0; |
152 | } |
153 | x = file[pos]; |
154 | x = (x << 8) + file[pos + 1]; |
155 | x = (x << 8) + file[pos + 2]; |
156 | x = (x << 8) + file[pos + 3]; |
157 | if (x & 0x80000000) { |
158 | x |= ~0xffffffff; |
159 | } |
160 | return x; |
161 | } |
162 | |
163 | unsigned int FoFiBase::getU32BE(int pos, bool *ok) const |
164 | { |
165 | unsigned int x; |
166 | |
167 | if (pos < 0 || pos > INT_MAX - 3 || pos + 3 >= len) { |
168 | *ok = false; |
169 | return 0; |
170 | } |
171 | x = file[pos]; |
172 | x = (x << 8) + file[pos + 1]; |
173 | x = (x << 8) + file[pos + 2]; |
174 | x = (x << 8) + file[pos + 3]; |
175 | return x; |
176 | } |
177 | |
178 | unsigned int FoFiBase::getU32LE(int pos, bool *ok) const |
179 | { |
180 | unsigned int x; |
181 | |
182 | if (pos < 0 || pos > INT_MAX - 3 || pos + 3 >= len) { |
183 | *ok = false; |
184 | return 0; |
185 | } |
186 | x = file[pos + 3]; |
187 | x = (x << 8) + file[pos + 2]; |
188 | x = (x << 8) + file[pos + 1]; |
189 | x = (x << 8) + file[pos]; |
190 | return x; |
191 | } |
192 | |
193 | unsigned int FoFiBase::getUVarBE(int pos, int size, bool *ok) const |
194 | { |
195 | unsigned int x; |
196 | int i; |
197 | |
198 | if (pos < 0 || pos > INT_MAX - size || pos + size > len) { |
199 | *ok = false; |
200 | return 0; |
201 | } |
202 | x = 0; |
203 | for (i = 0; i < size; ++i) { |
204 | x = (x << 8) + file[pos + i]; |
205 | } |
206 | return x; |
207 | } |
208 | |
209 | bool FoFiBase::checkRegion(int pos, int size) const |
210 | { |
211 | return pos >= 0 && size >= 0 && pos < INT_MAX - size && size < INT_MAX - pos && pos + size >= pos && pos + size <= len; |
212 | } |
213 | |