/src/libredwg/src/decode.c
Line | Count | Source |
1 | | /*****************************************************************************/ |
2 | | /* LibreDWG - free implementation of the DWG file format */ |
3 | | /* */ |
4 | | /* Copyright (C) 2009-2010,2018-2026 Free Software Foundation, Inc. */ |
5 | | /* */ |
6 | | /* This library is free software, licensed under the terms of the GNU */ |
7 | | /* General Public License as published by the Free Software Foundation, */ |
8 | | /* either version 3 of the License, or (at your option) any later version. */ |
9 | | /* You should have received a copy of the GNU General Public License */ |
10 | | /* along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
11 | | /*****************************************************************************/ |
12 | | |
13 | | /* |
14 | | * decode.c: decoding functions |
15 | | * written by Felipe Castro |
16 | | * modified by Felipe Corrêa da Silva Sances |
17 | | * modified by Rodrigo Rodrigues da Silva |
18 | | * modified by Till Heuschmann |
19 | | * modified by Reini Urban |
20 | | * modified by Denis Pruchkovsky |
21 | | * modified by Michal Josef Špaček |
22 | | */ |
23 | | |
24 | | #define _DEFAULT_SOURCE 1 // for endian byteswaps |
25 | | #define _BSD_SOURCE 1 |
26 | | #define _GNU_SOURCE 1 /* for memmem on linux */ |
27 | | #ifdef __STDC_ALLOC_LIB__ |
28 | | # define __STDC_WANT_LIB_EXT2__ 1 /* for strdup */ |
29 | | #else |
30 | | # define _USE_BSD 1 |
31 | | #endif |
32 | | #include "config.h" |
33 | | #include <stdio.h> |
34 | | #include <stdlib.h> |
35 | | #include <string.h> |
36 | | #include <stdbool.h> |
37 | | #include <assert.h> |
38 | | #include <limits.h> |
39 | | |
40 | | #define IS_DECODER |
41 | | #include "common.h" |
42 | | #include "bits.h" |
43 | | #include "dwg.h" |
44 | | #include "hash.h" |
45 | | #include "decode.h" |
46 | | #include "print.h" |
47 | | #include "free.h" |
48 | | #include "dynapi.h" |
49 | | |
50 | | /* the current version per spec block */ |
51 | | static int cur_ver = 0; |
52 | | static BITCODE_BL rcount1 = 0, rcount2 = 0; |
53 | | static bool is_teigha = false; |
54 | | |
55 | | #ifdef DWG_ABORT |
56 | | static unsigned int errors = 0; |
57 | | # ifndef DWG_ABORT_LIMIT |
58 | | # define DWG_ABORT_LIMIT 200 |
59 | | # endif |
60 | | #endif |
61 | | |
62 | | #ifdef USE_TRACING |
63 | | /* This flag means we have checked the environment variable |
64 | | LIBREDWG_TRACE and set `loglevel' appropriately. */ |
65 | | static bool env_var_checked_p; |
66 | | #endif /* USE_TRACING */ |
67 | 386M | #define DWG_LOGLEVEL loglevel |
68 | | |
69 | | #include "logging.h" |
70 | | #include "dec_macros.h" |
71 | | |
72 | | // #undef LOG_POS |
73 | | // #define LOG_POS LOG_INSANE (" @%" PRIuSIZE ".%u\n", dat->byte, dat->bit); |
74 | | |
75 | | /*------------------------------------------------------------------------------ |
76 | | * Private functions |
77 | | */ |
78 | | |
79 | | static int decode_R13_R2000 (Bit_Chain *restrict dat, Dwg_Data *restrict dwg); |
80 | | static int decode_R2004 (Bit_Chain *restrict dat, Dwg_Data *restrict dwg); |
81 | | static int decode_R2007 (Bit_Chain *restrict dat, Dwg_Data *restrict dwg); |
82 | | |
83 | | static int dwg_decode_ole2 (Dwg_Entity_OLE2FRAME *restrict _obj); |
84 | | |
85 | | static int dwg_decode_common_entity_handle_data (Bit_Chain *dat, |
86 | | Bit_Chain *hdl_dat, |
87 | | Dwg_Object *restrict obj); |
88 | | static int resolve_objectref_vector (Bit_Chain *restrict dat, |
89 | | Dwg_Data *restrict dwg); |
90 | | static int dwg_validate_entity_links (Dwg_Data *restrict dwg); |
91 | | static int secondheader_private (Bit_Chain *restrict dat, |
92 | | Dwg_Data *restrict dwg); |
93 | | static int objfreespace_private (Bit_Chain *restrict dat, |
94 | | Dwg_Data *restrict dwg); |
95 | | |
96 | | /*---------------------------------------------------------------------------- |
97 | | * Public variables |
98 | | */ |
99 | | // long unsigned int ktl_lastaddress; |
100 | | |
101 | | /*---------------------------------------------------------------------------- |
102 | | * Public function definitions |
103 | | */ |
104 | | |
105 | | /** dwg_decode |
106 | | * returns 0 on success. |
107 | | * |
108 | | * everything in dwg is cleared |
109 | | * and then either read from dat, or set to a default. |
110 | | */ |
111 | | EXPORT int |
112 | | dwg_decode (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
113 | 22.4k | { |
114 | 22.4k | char magic[11]; |
115 | | |
116 | 22.4k | dwg->num_object_refs = 0; |
117 | | // dwg->num_layers = 0; // see now dwg->layer_control->num_entries |
118 | 22.4k | dwg->num_entities = 0; |
119 | 22.4k | dwg->num_objects = 0; |
120 | 22.4k | dwg->num_classes = 0; |
121 | 22.4k | dwg->thumbnail.size = 0; |
122 | 22.4k | dwg->thumbnail.chain = NULL; |
123 | 22.4k | dwg->header.num_sections = 0; |
124 | 22.4k | dwg->header.section_infohdr.num_desc = 0; |
125 | 22.4k | dwg->dwg_class = NULL; |
126 | 22.4k | dwg->object_ref = NULL; |
127 | 22.4k | dwg->object = NULL; |
128 | 22.4k | if (dwg->object_ordered_ref) |
129 | 0 | { |
130 | 0 | free (dwg->object_ordered_ref); |
131 | 0 | dwg->object_ordered_ref = NULL; |
132 | 0 | } |
133 | 22.4k | dwg->num_object_ordered_refs = 0; |
134 | 22.4k | dwg->object_map = hash_new (dat->size / 1000); |
135 | 22.4k | if (!dwg->object_map) |
136 | 0 | { |
137 | | // whatever, we are obviously on a tiny system |
138 | 0 | dwg->object_map = hash_new (1024); |
139 | 0 | if (!dwg->object_map) |
140 | 0 | { |
141 | 0 | LOG_ERROR ("Out of memory"); |
142 | 0 | return DWG_ERR_OUTOFMEM; |
143 | 0 | } |
144 | 0 | } |
145 | 22.4k | dwg->dirty_refs = 1; |
146 | | |
147 | | // memset (&dwg->header, 0, sizeof (dwg->header)); // no, needed for magic |
148 | 22.4k | memset (&dwg->header_vars, 0, sizeof (dwg->header_vars)); |
149 | 22.4k | memset (&dwg->summaryinfo, 0, sizeof (dwg->summaryinfo)); |
150 | 22.4k | memset (&dwg->fhdr.r2004_header, 0, sizeof (dwg->fhdr.r2004_header)); |
151 | 22.4k | memset (&dwg->auxheader, 0, sizeof (dwg->auxheader)); |
152 | 22.4k | memset (&dwg->secondheader, 0, sizeof (dwg->secondheader)); |
153 | 22.4k | memset (&dwg->objfreespace, 0, sizeof (dwg->objfreespace)); |
154 | | |
155 | 22.4k | if (dwg->opts) |
156 | 0 | { |
157 | 0 | loglevel = dwg->opts & DWG_OPTS_LOGLEVEL; |
158 | 0 | dat->opts = dwg->opts; |
159 | 0 | } |
160 | | |
161 | | #ifdef USE_TRACING |
162 | | /* Before starting, set the logging level, but only do so once. */ |
163 | | if (!env_var_checked_p) |
164 | | { |
165 | | char *probe = getenv ("LIBREDWG_TRACE"); |
166 | | if (probe) |
167 | | loglevel = atoi (probe); |
168 | | env_var_checked_p = true; |
169 | | } |
170 | | #endif /* USE_TRACING */ |
171 | | |
172 | | /* Version */ |
173 | 22.4k | dat->byte = 0; |
174 | 22.4k | dat->bit = 0; |
175 | 22.4k | if (!dat->chain |
176 | 22.4k | || dat->size < 58) // saw the smallest r2.10 DWG with 1095 bytes |
177 | 0 | { |
178 | 0 | LOG_ERROR ("dwg too small: %" PRIuSIZE " bytes", dat->size); |
179 | 0 | return DWG_ERR_INVALIDDWG; |
180 | 0 | } |
181 | 22.4k | strncpy (magic, (const char *)dat->chain, 11); |
182 | 22.4k | magic[10] = '\0'; |
183 | | |
184 | 22.4k | dwg->header.from_version = dwg_version_hdr_type (magic); |
185 | 22.4k | if (!dwg->header.from_version) |
186 | 87 | { |
187 | 87 | if (strncmp (magic, "AC", 2)) // let's ignore MC0.0 for now |
188 | 0 | { |
189 | 0 | LOG_ERROR ("Invalid DWG, magic: %s", magic); |
190 | 0 | } |
191 | 87 | else |
192 | 87 | { |
193 | 87 | LOG_ERROR ("Invalid or unimplemented DWG version code %s", magic); |
194 | 87 | } |
195 | 87 | return DWG_ERR_INVALIDDWG; |
196 | 87 | } |
197 | 22.4k | dat->from_version = dwg->header.from_version; |
198 | 22.4k | if (!dwg->header.version) // target version not set |
199 | 22.4k | { |
200 | 22.4k | dat->version = dwg->header.version = dat->from_version; |
201 | 22.4k | } |
202 | 22.4k | LOG_INFO ("This file's version code is: %s (%s)\n", magic, |
203 | 22.4k | dwg_version_type (dat->from_version)); |
204 | | |
205 | 22.4k | dat->byte = 0xb; // After magic string. |
206 | 22.4k | PRE (R_13b1) |
207 | 2.80k | { |
208 | 2.80k | Dwg_Object *ctrl; |
209 | 2.80k | int error = decode_preR13 (dat, dwg); |
210 | 2.80k | if (error <= DWG_ERR_CRITICAL) |
211 | 1.51k | { |
212 | 1.51k | ctrl = &dwg->object[0]; |
213 | 1.51k | dwg->block_control = *ctrl->tio.object->tio.BLOCK_CONTROL; |
214 | 1.51k | } |
215 | 2.80k | return error; |
216 | 2.80k | } |
217 | 19.5k | VERSIONS (R_13b1, R_2000) |
218 | 19.5k | { |
219 | 19.5k | return decode_R13_R2000 (dat, dwg); |
220 | 19.5k | } |
221 | 40 | VERSIONS (R_2004a, R_2004) |
222 | 0 | { |
223 | 0 | return decode_R2004 (dat, dwg); |
224 | 0 | } |
225 | 40 | VERSIONS (R_2007a, R_2007) |
226 | 40 | { |
227 | 40 | return decode_R2007 (dat, dwg); |
228 | 40 | } |
229 | 0 | SINCE (R_2010b) |
230 | 0 | { |
231 | 0 | read_r2007_init (dwg); // sets loglevel only for now |
232 | 0 | return decode_R2004 (dat, dwg); |
233 | 0 | } |
234 | | |
235 | | // This line should not be reached |
236 | 0 | LOG_ERROR ("LibreDWG does not support this DWG version: %s (%s).", magic, |
237 | 0 | dwg_version_type (dat->from_version)); |
238 | 0 | return DWG_ERR_INVALIDDWG; |
239 | 0 | } |
240 | | |
241 | | /* ODA 3.2.6 SECTION-LOCATOR RECORDS: p.21 |
242 | | This is an ODA calculation mistake, it's not needed at all. |
243 | | |
244 | | static BITCODE_RS |
245 | | xor_section_CRC (BITCODE_RL num_sections, BITCODE_RS crc) |
246 | | { |
247 | | switch (num_sections) |
248 | | { |
249 | | case 3: |
250 | | crc ^= 0xA598; |
251 | | break; |
252 | | case 4: |
253 | | crc ^= 0x8101; |
254 | | break; |
255 | | case 5: |
256 | | crc ^= 0x3CC4; |
257 | | break; |
258 | | case 6: |
259 | | crc ^= 0x8461; |
260 | | break; |
261 | | default: |
262 | | LOG_WARN ("Unknown num_sections " FORMAT_RL ", wrong Section CRC", |
263 | | num_sections); |
264 | | } |
265 | | return crc; |
266 | | } |
267 | | */ |
268 | | |
269 | | // may return OUTOFBOUNDS |
270 | | static int |
271 | | template_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
272 | 16 | { |
273 | 16 | Bit_Chain *str_dat = dat; |
274 | 16 | Dwg_Template *_obj = &dwg->Template; |
275 | 16 | Dwg_Object *obj = NULL; |
276 | 16 | int error = 0; |
277 | | |
278 | | // clang-format off |
279 | 16 | #include "template.spec" |
280 | | // clang-format on |
281 | | |
282 | 16 | dwg->header_vars.MEASUREMENT = _obj->MEASUREMENT; |
283 | 16 | LOG_TRACE ("-> HEADER.MEASUREMENT: " FORMAT_BS " (0 English/1 Metric)\n", |
284 | 16 | dwg->header_vars.MEASUREMENT); |
285 | | |
286 | 16 | return error; |
287 | 16 | } |
288 | | |
289 | | static int |
290 | | decode_R13_R2000 (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
291 | 19.5k | { |
292 | 19.5k | Dwg_Object *obj = NULL; |
293 | 19.5k | unsigned int section_size = 0; |
294 | 19.5k | BITCODE_RS crc, crc2; |
295 | 19.5k | size_t size, startpos, endpos, lastmap, pvz = 0; |
296 | 19.5k | size_t object_begin, object_end; |
297 | 19.5k | BITCODE_BL j; |
298 | 19.5k | int error = 0; |
299 | 19.5k | int sentinel_size = 16; |
300 | 19.5k | const char *section_names[] |
301 | 19.5k | = { "AcDb:Header", "AcDb:Classes", "AcDb:Handles", |
302 | 19.5k | "AcDb:ObjFreeSpace", "AcDb:Template", "AcDb:AuxHeader" }; |
303 | | |
304 | 19.5k | { |
305 | 19.5k | Dwg_Header *_obj = &dwg->header; |
306 | 19.5k | Bit_Chain *hdl_dat = dat; |
307 | 19.5k | int i; |
308 | 19.5k | BITCODE_BL vcount; |
309 | 19.5k | assert (dat->byte == 0xb); // after version magic |
310 | | |
311 | | // clang-format off |
312 | 19.5k | #include "header.spec" |
313 | | // clang-format on |
314 | 19.5k | } |
315 | 19.5k | if ((error = dwg_sections_init (dwg))) |
316 | 0 | return error; |
317 | 19.5k | if (dat->byte != 0x19) |
318 | 0 | { |
319 | 0 | LOG_ERROR ("Wrong HEADER Section Locator Records at %" PRIuSIZE, |
320 | 0 | dat->byte); |
321 | 0 | return DWG_ERR_INVALIDDWG; |
322 | 0 | } |
323 | 19.5k | assert (dat->byte == 0x19); |
324 | | /* section 0: header vars |
325 | | * 1: class section |
326 | | * 2: Handles (object map) |
327 | | * 3: optional: ObjFreeSpace |
328 | | * -: 2ndHeader and its sentinels |
329 | | * 4: optional: Template (MEASUREMENT) |
330 | | * 5: optional: AuxHeader (no sentinels, since R13c3) |
331 | | */ |
332 | 79.0k | for (j = 0; j < dwg->header.sections; j++) |
333 | 59.5k | { |
334 | 59.5k | dwg->header.section[j].number = (BITCODE_RLd)bit_read_RC (dat); |
335 | 59.5k | dwg->header.section[j].address = (BITCODE_RLL)bit_read_RL (dat); |
336 | 59.5k | dwg->header.section[j].size = bit_read_RL (dat); |
337 | 59.5k | if (j < 6) |
338 | 59.5k | strcpy (dwg->header.section[j].name, section_names[j]); |
339 | 59.5k | LOG_TRACE ("section[%u].number: %8d [RC] %s\n", j, |
340 | 59.5k | (int)dwg->header.section[j].number, |
341 | 59.5k | dwg->header.section[j].name); |
342 | 59.5k | LOG_TRACE ("section[%u].address: %8u [RL]\n", j, |
343 | 59.5k | (unsigned)dwg->header.section[j].address); |
344 | 59.5k | LOG_TRACE ("section[%u].size: %8u [RL]\n", j, |
345 | 59.5k | (unsigned)dwg->header.section[j].size); |
346 | 59.5k | if (dwg->header.section[j].address + dwg->header.section[j].size |
347 | 59.5k | > dat->size) |
348 | 1 | { |
349 | 1 | LOG_ERROR ("section[%u] address or size overflow: %" PRIu64 |
350 | 1 | " + " FORMAT_RL " > %" PRIuSIZE, |
351 | 1 | j, dwg->header.section[j].address, |
352 | 1 | dwg->header.section[j].size, dat->size); |
353 | 1 | return DWG_ERR_INVALIDDWG; |
354 | 1 | } |
355 | 59.5k | } |
356 | | |
357 | | // Check CRC up to now (note: ODA has a bug here) |
358 | 19.5k | crc2 = bit_calc_CRC (0xC0C1, &dat->chain[0], dat->byte); // from 0 to now |
359 | 19.5k | crc = bit_read_RS (dat); |
360 | 19.5k | LOG_TRACE ("crc: %04X [RSx] from 0-%" PRIuSIZE "\n", (unsigned)crc, |
361 | 19.5k | dat->byte - 2); |
362 | 19.5k | if (crc != crc2) |
363 | 19.5k | { |
364 | 19.5k | LOG_ERROR ("Header CRC mismatch %04X <=> %04X", (unsigned)crc, |
365 | 19.5k | (unsigned)crc2); |
366 | 19.5k | error |= DWG_ERR_WRONGCRC; |
367 | 19.5k | } |
368 | | |
369 | 19.5k | if (bit_search_sentinel (dat, dwg_sentinel (DWG_SENTINEL_HEADER_END))) |
370 | 19.5k | LOG_TRACE (" HEADER (end): %4u\n", (unsigned)dat->byte); |
371 | | |
372 | | /*------------------------------------------------------------------------- |
373 | | * Section 5 AuxHeader |
374 | | * R13c3+, mostly redundant file header information. no sentinels |
375 | | */ |
376 | 19.5k | if (dwg->header.sections == 6 && dwg->header.version >= R_13c3) |
377 | 13 | { |
378 | 13 | Dwg_AuxHeader *_obj = &dwg->auxheader; |
379 | 13 | Bit_Chain *hdl_dat = dat; |
380 | 13 | size_t end_address = dwg->header.section[SECTION_AUXHEADER_R2000].address |
381 | 13 | + dwg->header.section[SECTION_AUXHEADER_R2000].size; |
382 | | |
383 | 13 | obj = NULL; |
384 | 13 | dat->byte = dwg->header.section[SECTION_AUXHEADER_R2000].address; |
385 | 13 | LOG_TRACE ("\n" |
386 | 13 | "=======> AuxHeader: %4zu\n", |
387 | 13 | dat->byte); |
388 | 13 | LOG_TRACE (" AuxHeader (end): %4zu\n", end_address); |
389 | 13 | if (dat->size < end_address) |
390 | 0 | { |
391 | 0 | LOG_ERROR ("Invalid AuxHeader size: buffer overflow"); |
392 | 0 | error |= DWG_ERR_SECTIONNOTFOUND; |
393 | 0 | } |
394 | 13 | else |
395 | 13 | { |
396 | 13 | size_t old_size = dat->size; |
397 | 13 | BITCODE_BL vcount; |
398 | 13 | dat->size = end_address; |
399 | | // clang-format off |
400 | 13 | #include "auxheader.spec" |
401 | | // clang-format on |
402 | 13 | dat->size = old_size; |
403 | 13 | } |
404 | 13 | } |
405 | | |
406 | | /*------------------------------------------------------------------------- |
407 | | * Thumbnail Image (pre-r13c3 before, since r13c3 at the end) |
408 | | */ |
409 | 19.5k | if (bit_search_sentinel (dat, dwg_sentinel (DWG_SENTINEL_THUMBNAIL_BEGIN))) |
410 | 0 | { |
411 | 0 | size_t start_address; |
412 | |
|
413 | 0 | dat->bit = 0; |
414 | 0 | start_address = dat->byte; |
415 | 0 | LOG_TRACE ("\n=======> Thumbnail: %4zu\n", start_address - 16); |
416 | 0 | if (dwg->header.thumbnail_address |
417 | 0 | && dwg->header.thumbnail_address != (BITCODE_RL)(dat->byte - 16)) |
418 | 0 | LOG_WARN ("Illegal header.thumbnail_address: %i != %" PRIuSIZE, |
419 | 0 | dwg->header.thumbnail_address, dat->byte - 16); |
420 | 0 | dwg->header.thumbnail_address = (dat->byte - 16) & 0xFFFFFFFF; |
421 | 0 | if (bit_search_sentinel (dat, dwg_sentinel (DWG_SENTINEL_THUMBNAIL_END))) |
422 | 0 | { |
423 | 0 | BITCODE_RL bmpsize; |
424 | 0 | LOG_TRACE (" Thumbnail (end): %4zu\n", dat->byte); |
425 | 0 | if ((dat->byte - 16) < start_address) |
426 | 0 | { |
427 | 0 | LOG_ERROR ("Illegal header.thumbnail_size: %" PRIuSIZE |
428 | 0 | " < %" PRIuSIZE, |
429 | 0 | dat->byte - 16, start_address); |
430 | 0 | } |
431 | 0 | else if ((dat->byte - 16) - start_address < 10) |
432 | 0 | { |
433 | 0 | LOG_TRACE ("No header.thumbnail: %" PRIuSIZE " < 10", |
434 | 0 | dat->byte - 16 - start_address); |
435 | 0 | } |
436 | 0 | else |
437 | 0 | { |
438 | 0 | BITCODE_RC type; |
439 | 0 | assert ((dat->byte - 16) >= start_address); |
440 | 0 | dwg->thumbnail.size = (dat->byte - 16) - start_address; |
441 | 0 | dwg->thumbnail.chain |
442 | 0 | = (unsigned char *)calloc (dwg->thumbnail.size, 1); |
443 | 0 | dwg->thumbnail.byte = 0; |
444 | 0 | if (!dwg->thumbnail.chain) |
445 | 0 | { |
446 | 0 | LOG_ERROR ("Out of memory"); |
447 | 0 | return DWG_ERR_OUTOFMEM; |
448 | 0 | } |
449 | 0 | memcpy (dwg->thumbnail.chain, &dat->chain[start_address], |
450 | 0 | dwg->thumbnail.size); |
451 | 0 | dat->byte += dwg->thumbnail.size; |
452 | 0 | dwg_bmp (dwg, &bmpsize, &type); |
453 | 0 | if (bmpsize > dwg->thumbnail.size) |
454 | 0 | LOG_ERROR ("thumbnail size overflow: %i > %" PRIuSIZE "\n", |
455 | 0 | bmpsize, dwg->thumbnail.size); |
456 | 0 | } |
457 | 0 | } |
458 | 0 | } |
459 | | |
460 | | /*------------------------------------------------------------------------- |
461 | | * Header Variables, section 0 |
462 | | */ |
463 | | |
464 | 19.5k | LOG_INFO ("\n" |
465 | 19.5k | "=======> Header Variables: %4u\n", |
466 | 19.5k | (unsigned int)dwg->header.section[SECTION_HEADER_R13].address); |
467 | 19.5k | LOG_INFO (" Header Variables (end): %4u\n", |
468 | 19.5k | (unsigned int)(dwg->header.section[SECTION_HEADER_R13].address |
469 | 19.5k | + dwg->header.section[SECTION_HEADER_R13].size)); |
470 | 19.5k | if (dwg->header.section[SECTION_HEADER_R13].address < 58 |
471 | 19.4k | || dwg->header.section[SECTION_HEADER_R13].address |
472 | 19.4k | + dwg->header.section[SECTION_HEADER_R13].size |
473 | 19.4k | > dat->size) |
474 | 82 | { |
475 | 82 | LOG_ERROR ("Invalid Header section, skipped"); |
476 | 82 | error |= DWG_ERR_SECTIONNOTFOUND; |
477 | 82 | goto classes_section; |
478 | 82 | } |
479 | | // after sentinel |
480 | 19.4k | dat->byte = pvz = dwg->header.section[SECTION_HEADER_R13].address + 16; |
481 | | // LOG_HANDLE ("@ 0x" FORMAT_HV ".%" PRIuSIZE "\n", bit_position (dat)/8, |
482 | | // bit_position (dat)%8); |
483 | 38.9k | #define MAX_HEADER_SIZE 2048 |
484 | 19.4k | dwg->header_vars.size = bit_read_RL (dat); |
485 | 19.4k | LOG_TRACE (" Length: " FORMAT_RL " [RL]\n", dwg->header_vars.size); |
486 | 19.4k | if (dwg->header_vars.size > MAX_HEADER_SIZE) |
487 | 14.5k | { |
488 | 14.5k | LOG_WARN ("Fixup illegal Header Length"); |
489 | 14.5k | dwg->header_vars.size = dwg->header.section[SECTION_HEADER_R13].size; |
490 | 14.5k | if (dwg->header_vars.size > 20) |
491 | 3.13k | dwg->header_vars.size -= (16 + 4); |
492 | 14.5k | } |
493 | 19.4k | dat->bit = 0; |
494 | | |
495 | 19.4k | error |= dwg_decode_header_variables (dat, dat, dat, dwg); |
496 | | |
497 | | // LOG_HANDLE ("@ 0x" FORMAT_HV ".%" PRIuSIZE "\n", bit_position (dat)/8, |
498 | | // bit_position (dat)%8); check slack Check CRC, hardcoded to 2 before end |
499 | | // sentinel |
500 | 19.4k | if (dwg->header_vars.size < MAX_HEADER_SIZE) |
501 | 19.4k | { |
502 | 19.4k | size_t crcpos = pvz + dwg->header_vars.size + 4; |
503 | 19.4k | if (dat->bit || dat->byte != crcpos) |
504 | 19.4k | { |
505 | 19.4k | unsigned char r = 8 - dat->bit; |
506 | 19.4k | LOG_HANDLE (" padding: %zd byte, %d bits\n", crcpos - dat->byte, r); |
507 | 19.4k | } |
508 | 19.4k | LOG_HANDLE (" crc pos: %" PRIuSIZE "\n", crcpos); |
509 | 19.4k | bit_set_position (dat, crcpos * 8); |
510 | 19.4k | crc = bit_read_RS (dat); |
511 | 19.4k | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE) |
512 | 19.4k | LOG_HANDLE ("crc: %04X [RSx] from %" PRIuSIZE "-%" PRIuSIZE "=%zd\n", |
513 | 19.4k | crc, pvz, dat->byte - 2, dat->byte - 2 - pvz); |
514 | 19.4k | else |
515 | 19.4k | LOG_TRACE ("crc: %04X [RSx] %zd\n", crc, dat->byte - 2 - pvz); |
516 | 19.4k | } |
517 | 10 | else |
518 | 10 | { |
519 | 10 | LOG_WARN ("Skip crc with illegal Header Length"); |
520 | 10 | error |= DWG_ERR_SECTIONNOTFOUND; |
521 | 10 | goto classes_section; |
522 | 10 | } |
523 | 19.4k | crc2 = 0; |
524 | | // LOG_HANDLE ("@ 0x" FORMAT_HV "\n", bit_position (dat)/8); |
525 | | // LOG_HANDLE ("HEADER_R13.address of size 0x" FORMAT_HV "\n", pvz); |
526 | | // LOG_HANDLE ("HEADER_R13.size %d\n", |
527 | | // dwg->header.section[SECTION_HEADER_R13].size); |
528 | | // typical sizes: 400-599 |
529 | 19.4k | if (dwg->header.section[SECTION_HEADER_R13].size > 34 |
530 | 4.35k | && dwg->header.section[SECTION_HEADER_R13].size < 0xfff |
531 | 4.35k | && pvz < dat->byte |
532 | 4.35k | && pvz + dwg->header.section[SECTION_HEADER_R13].size < dat->size) |
533 | 4.35k | { |
534 | | // not dwg->header_vars.size, rather -4 (minus the section_size). |
535 | | // section_size + data, i.e. minus the 2x sentinel (32) + crc itself (2) |
536 | | // if we would include the crc we would always get 0000 |
537 | 4.35k | BITCODE_RL crc_size = dwg->header.section[SECTION_HEADER_R13].size - 34; |
538 | 4.35k | LOG_HANDLE (" calc header crc size: " FORMAT_RL "\n", crc_size); |
539 | 4.35k | crc2 = bit_calc_CRC (0xC0C1, &dat->chain[pvz], crc_size); |
540 | 4.35k | } |
541 | 19.4k | if (crc != crc2) |
542 | 14.2k | { |
543 | 14.2k | LOG_WARN ("Header Section[%d] CRC mismatch %04X <=> %04X", |
544 | 14.2k | (int)dwg->header.section[SECTION_HEADER_R13].number, crc, |
545 | 14.2k | crc2); |
546 | 14.2k | error |= DWG_ERR_WRONGCRC; |
547 | 14.2k | } |
548 | | |
549 | | /*------------------------------------------------------------------------- |
550 | | * Classes, section 1 |
551 | | */ |
552 | 19.5k | classes_section: |
553 | 19.5k | LOG_INFO ("\n" |
554 | 19.5k | "=======> Classes (start): %4lu\n", |
555 | 19.5k | (long)dwg->header.section[SECTION_CLASSES_R13].address); |
556 | 19.5k | LOG_INFO (" Classes (end) : %4lu\n", |
557 | 19.5k | (long)(dwg->header.section[SECTION_CLASSES_R13].address |
558 | 19.5k | + dwg->header.section[SECTION_CLASSES_R13].size)); |
559 | 19.5k | dat->byte = dwg->header.section[SECTION_CLASSES_R13].address; |
560 | 19.5k | if (dwg->header.section[SECTION_CLASSES_R13].size < 30) |
561 | 16.3k | { |
562 | 16.3k | LOG_ERROR ("Classes section too small, skipped"); |
563 | 16.3k | error |= DWG_ERR_SECTIONNOTFOUND; |
564 | 16.3k | goto handles_section; |
565 | 16.3k | } |
566 | | // check sentinel |
567 | 3.15k | if (memcmp (dwg_sentinel (DWG_SENTINEL_CLASS_BEGIN), &dat->chain[dat->byte], |
568 | 3.15k | 16) |
569 | 3.15k | == 0) |
570 | 0 | { |
571 | 0 | dat->byte += 16; |
572 | 0 | } |
573 | 3.15k | else |
574 | 3.15k | { |
575 | 3.15k | sentinel_size = 0; |
576 | 3.15k | LOG_TRACE ("no class sentinel\n"); |
577 | 3.15k | } |
578 | 3.15k | dat->bit = 0; |
579 | 3.15k | size = bit_read_RL (dat); |
580 | 3.15k | LOG_TRACE (" Size : %" PRIuSIZE " [RL]\n", size); |
581 | 3.15k | if (size |
582 | 3.15k | != dwg->header.section[SECTION_CLASSES_R13].size |
583 | 3.15k | - ((sentinel_size * 2) + 6)) |
584 | 2.73k | { |
585 | 2.73k | endpos = dwg->header.section[SECTION_CLASSES_R13].address |
586 | 2.73k | + dwg->header.section[SECTION_CLASSES_R13].size - sentinel_size; |
587 | 2.73k | LOG_ERROR ("Invalid size %" PRIuSIZE ", should be: " FORMAT_RL |
588 | 2.73k | ", endpos: %" PRIuSIZE "\n", |
589 | 2.73k | size, |
590 | 2.73k | dwg->header.section[SECTION_CLASSES_R13].size |
591 | 2.73k | - ((sentinel_size * 2) + 6), |
592 | 2.73k | endpos); |
593 | 2.73k | error |= DWG_ERR_SECTIONNOTFOUND; |
594 | 2.73k | goto handles_section; |
595 | 2.73k | } |
596 | 426 | else |
597 | 426 | endpos = dat->byte + size; |
598 | 426 | LOG_INSANE ("endpos: %" PRIuSIZE, endpos); |
599 | 426 | LOG_POS_ (INSANE); |
600 | | |
601 | | /* Read the classes |
602 | | */ |
603 | 426 | dwg->layout_type = 0; |
604 | 426 | dwg->num_classes = 0; |
605 | | |
606 | | #if 0 |
607 | | SINCE (R_2004a) // dead code. see read_2004_section_classes() instead |
608 | | { |
609 | | BITCODE_B btrue; |
610 | | BITCODE_BS max_num; |
611 | | BITCODE_RS rs_zero; |
612 | | max_num = bit_read_BS (dat); |
613 | | LOG_TRACE ("2004 max_num: " FORMAT_BS " [BS]\n", max_num); |
614 | | rs_zero = bit_read_RS (dat); |
615 | | LOG_TRACE ("2004 rs_zero: " FORMAT_RS " [RS]\n", rs_zero); |
616 | | btrue = bit_read_B (dat); // always 1 |
617 | | LOG_TRACE ("2004 btrue: " FORMAT_B " [B]\n", btrue); |
618 | | } |
619 | | #endif |
620 | | |
621 | 1.15k | while (dat->byte < endpos - 1) |
622 | 862 | { |
623 | 862 | BITCODE_BS i; |
624 | 862 | Dwg_Class *klass; |
625 | | |
626 | 862 | i = dwg->num_classes; |
627 | | /* CWE-400: bound max classes to prevent DoS via crafted input. |
628 | | Each class entry is at minimum ~10 bytes on disk; |
629 | | sizeof(Dwg_Class) is a very generous upper bound. */ |
630 | 862 | if ((size_t)i >= 100 + (size / sizeof (Dwg_Class)) || i >= 65535) |
631 | 0 | { |
632 | 0 | LOG_ERROR ("Too many classes: %u, max %" PRIuSIZE, (unsigned)i, |
633 | 0 | 100 + (size / sizeof (Dwg_Class))); |
634 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
635 | 0 | goto handles_section; |
636 | 0 | } |
637 | 862 | if (i == 0) |
638 | 426 | dwg->dwg_class = (Dwg_Class *)malloc (sizeof (Dwg_Class)); |
639 | 436 | else |
640 | 436 | dwg->dwg_class = (Dwg_Class *)realloc (dwg->dwg_class, |
641 | 436 | (i + 1) * sizeof (Dwg_Class)); |
642 | 862 | if (!dwg->dwg_class) |
643 | 0 | { |
644 | 0 | LOG_ERROR ("Out of memory"); |
645 | 0 | return DWG_ERR_OUTOFMEM; |
646 | 0 | } |
647 | 862 | klass = &dwg->dwg_class[i]; |
648 | 862 | memset (klass, 0, sizeof (Dwg_Class)); |
649 | 862 | klass->number = bit_read_BS (dat); |
650 | 862 | LOG_HANDLE ("-------------------\n"); |
651 | 862 | LOG_HANDLE ("Number: " FORMAT_BS " [BS]", klass->number); |
652 | 862 | LOG_POS_ (HANDLE); |
653 | 862 | klass->proxyflag = bit_read_BS (dat); |
654 | 862 | LOG_HANDLE ("Proxyflag: " FORMAT_BS " [BS]", klass->proxyflag); |
655 | 862 | LOG_POS_ (HANDLE); |
656 | 862 | dwg_log_proxyflag (DWG_LOGLEVEL, DWG_LOGLEVEL_HANDLE, klass->proxyflag); |
657 | 862 | if (dat->byte >= endpos) |
658 | 2 | break; |
659 | 860 | klass->appname = bit_read_TV (dat); |
660 | 860 | LOG_HANDLE ("Application name: \"%s\" [TV]", klass->appname); |
661 | 860 | LOG_POS_ (HANDLE); |
662 | 860 | if (dat->byte >= endpos) |
663 | 133 | { |
664 | 133 | free (klass->appname); |
665 | 133 | break; |
666 | 133 | } |
667 | 727 | klass->cppname = bit_read_TV (dat); |
668 | 727 | LOG_HANDLE ("C++ class name: %s [TV] ", klass->cppname); |
669 | 727 | LOG_POS_ (HANDLE); |
670 | 727 | klass->dxfname = bit_read_TV (dat); |
671 | 727 | LOG_HANDLE ("DXF record name: %s [TV] ", klass->dxfname); |
672 | 727 | LOG_POS_ (HANDLE); |
673 | 727 | klass->is_zombie = bit_read_B (dat); // was_a_proxy |
674 | 727 | LOG_HANDLE ("is_zombie: " FORMAT_B " [B] ", klass->is_zombie); |
675 | 727 | LOG_POS_ (HANDLE); |
676 | | // 1f2 for entities, 1f3 for objects |
677 | 727 | klass->item_class_id = bit_read_BS (dat); |
678 | 727 | LOG_HANDLE ("item_class_id: " FORMAT_BS " [BS]", |
679 | 727 | klass->item_class_id); |
680 | 727 | LOG_POS_ (HANDLE); |
681 | 727 | if (DWG_LOGLEVEL == DWG_LOGLEVEL_TRACE) |
682 | 0 | { |
683 | 0 | LOG (TRACE, |
684 | 0 | "Class %d 0x%x %s\n" |
685 | 0 | " %s \"%s\" %d 0x%x\n", |
686 | 0 | klass->number, klass->proxyflag, klass->dxfname, klass->cppname, |
687 | 0 | klass->appname, klass->is_zombie, klass->item_class_id); |
688 | 0 | } |
689 | | |
690 | | #if 0 |
691 | | SINCE (R_2007a) //? dead code it seems. see read_2004_section_classes() |
692 | | { |
693 | | klass->num_instances = bit_read_BL (dat); |
694 | | LOG_HANDLE ("num_instances: " FORMAT_BL " [BL]", klass->num_instances); LOG_POS_ (HANDLE); |
695 | | klass->dwg_version = bit_read_BL (dat); // nope: class_version |
696 | | klass->maint_version = bit_read_BL (dat); |
697 | | klass->unknown_1 = bit_read_BL (dat); |
698 | | klass->unknown_2 = bit_read_BL (dat); |
699 | | LOG_TRACE ( |
700 | | " num_instances: %d, dwg/maint version: %d/%d, unk: %d/%d\n", |
701 | | klass->num_instances, klass->dwg_version, klass->maint_version, |
702 | | klass->unknown_1, klass->unknown_2); |
703 | | } |
704 | | #endif |
705 | | |
706 | 727 | if (klass->dxfname && strEQc ((const char *)klass->dxfname, "LAYOUT")) |
707 | 0 | dwg->layout_type = klass->number; |
708 | | |
709 | 727 | dwg->num_classes++; |
710 | 727 | } |
711 | 426 | LOG_HANDLE ("-------------------\n"); |
712 | | |
713 | | // Check Section CRC |
714 | 426 | dat->byte = dwg->header.section[SECTION_CLASSES_R13].address |
715 | 426 | + dwg->header.section[SECTION_CLASSES_R13].size - 18; |
716 | 426 | dat->bit = 0; |
717 | 426 | pvz = dwg->header.section[SECTION_CLASSES_R13].address + 16; |
718 | 426 | if (!bit_check_CRC (dat, pvz, 0xC0C1)) |
719 | 426 | error |= DWG_ERR_WRONGCRC; |
720 | | |
721 | 426 | dat->byte += 16; // sentinel |
722 | 426 | pvz = bit_read_RL (dat); // Unknown bitlong inter class and object |
723 | 426 | LOG_TRACE ("unknown: 0x%04zx [RL] @%" PRIuSIZE "\n", pvz, dat->byte - 4); |
724 | 426 | LOG_INFO ("Number of classes read: %u\n", dwg->num_classes); |
725 | | |
726 | | /*------------------------------------------------------------------------- |
727 | | * Object-map, section 2 |
728 | | */ |
729 | 19.5k | handles_section: |
730 | 19.5k | dat->byte = dwg->header.section[SECTION_HANDLES_R13].address; |
731 | 19.5k | dat->bit = 0; |
732 | | |
733 | 19.5k | lastmap = dat->byte + dwg->header.section[SECTION_HANDLES_R13].size; // 4 |
734 | 19.5k | dwg->num_objects = 0; |
735 | 19.5k | object_begin = dat->size; |
736 | 19.5k | object_end = 0; |
737 | 19.5k | LOG_INFO ("\n" |
738 | 19.5k | "=======> Handles (start) : %8u\n", |
739 | 19.5k | (unsigned int)dwg->header.section[SECTION_HANDLES_R13].address); |
740 | 19.5k | LOG_INFO (" Handles (end) : %8u\n", |
741 | 19.5k | (unsigned int)(dwg->header.section[SECTION_HANDLES_R13].address |
742 | 19.5k | + dwg->header.section[SECTION_HANDLES_R13].size)); |
743 | 19.5k | LOG_INFO (" Length: %u\n", |
744 | 19.5k | (unsigned int)dwg->header.section[SECTION_HANDLES_R13].size); |
745 | | |
746 | 19.5k | do |
747 | 47.0k | { |
748 | 47.0k | BITCODE_RLL last_handle = 0; |
749 | 47.0k | size_t last_offset = 0; |
750 | 47.0k | size_t oldpos = 0; |
751 | 47.0k | BITCODE_RLL maxh |
752 | 47.0k | = (BITCODE_RLL)dwg->header.section[SECTION_HANDLES_R13].size << 1; |
753 | 47.0k | BITCODE_RLL max_handles |
754 | 47.0k | = maxh < INT32_MAX ? maxh |
755 | 47.0k | : dwg->header.section[SECTION_HANDLES_R13].size; |
756 | 47.0k | int added; |
757 | 47.0k | pvz = dat->byte; |
758 | | |
759 | 47.0k | startpos = dat->byte; |
760 | 47.0k | section_size = bit_read_RS_BE (dat); |
761 | 47.0k | LOG_TRACE ("Handles page size: %u [RS_BE]", section_size); |
762 | 47.0k | LOG_HANDLE (" @%" PRIuSIZE, startpos); |
763 | 47.0k | LOG_TRACE ("\n"); |
764 | 47.0k | if (section_size > 2040) |
765 | 18.3k | { |
766 | 18.3k | LOG_ERROR ("Object-map section size greater than 2040!"); |
767 | 18.3k | return DWG_ERR_VALUEOUTOFBOUNDS; |
768 | 18.3k | } |
769 | | |
770 | 13.2M | while (dat->byte - startpos < section_size) |
771 | 13.2M | { |
772 | 13.2M | BITCODE_MC prevsize; |
773 | 13.2M | BITCODE_UMC handleoff; |
774 | 13.2M | BITCODE_MC offset; |
775 | | // BITCODE_RLL last_handle = dwg->num_objects |
776 | | // ? dwg->object[dwg->num_objects - 1].handle.value : 0; |
777 | | |
778 | 13.2M | oldpos = dat->byte; |
779 | | // The offset from the previous handle. default: 1, unsigned. |
780 | | // Basically how many objects have been deleted here. |
781 | 13.2M | handleoff = bit_read_UMC (dat); |
782 | | // The offset from the previous address. default: obj->size, signed. |
783 | 13.2M | offset = bit_read_MC (dat); |
784 | 13.2M | prevsize = dwg->num_objects |
785 | 13.2M | ? dwg->object[dwg->num_objects - 1].size + 4 |
786 | 13.2M | : 0L; |
787 | | |
788 | 13.2M | if ((handleoff == 0) || (handleoff > (max_handles - last_handle)) |
789 | 7.79M | || (offset > -4 && offset < prevsize - 8)) |
790 | 7.55M | { |
791 | 7.55M | if (offset == prevsize) |
792 | 32.8k | LOG_WARN ("handleoff " FORMAT_UMC |
793 | 7.55M | " looks wrong, max_handles %x - " |
794 | 7.55M | "last_handle " FORMAT_HV " = " FORMAT_RLLx |
795 | 7.55M | " (@%" PRIuSIZE ")", |
796 | 7.55M | handleoff, (unsigned)max_handles, last_handle, |
797 | 7.55M | max_handles - last_handle, oldpos); |
798 | 7.55M | if (offset == 1 |
799 | 7.44M | || (offset > 0 && offset < prevsize && prevsize > 0) |
800 | 5.70M | || (offset < 0 && labs ((long)offset) < prevsize |
801 | 405k | && prevsize > 0)) |
802 | 2.25M | { |
803 | 2.25M | if (offset != prevsize) |
804 | 2.25M | LOG_WARN ("offset " FORMAT_MC |
805 | 2.25M | " looks wrong, should be prevsize " FORMAT_MC |
806 | 2.25M | " + 4", |
807 | 2.25M | offset, prevsize - 4); |
808 | | // handleoff = 1; |
809 | | // offset = prevsize; |
810 | | // LOG_WARN ("Recover invalid handleoff to %" PRIuSIZE " and |
811 | | // offset to %ld", |
812 | | // handleoff, offset); |
813 | 2.25M | } |
814 | 7.55M | } |
815 | 13.2M | last_offset += offset; |
816 | 13.2M | LOG_TRACE ("\nNext object: %lu ", (unsigned long)dwg->num_objects); |
817 | 13.2M | LOG_TRACE ("Handleoff: " FORMAT_UMC " [UMC]", handleoff); |
818 | 13.2M | LOG_HANDLE (" Offset: " FORMAT_MC " [MC] @%" PRIuSIZE, offset, |
819 | 13.2M | last_offset); |
820 | 13.2M | LOG_TRACE ("\n"); |
821 | | |
822 | 13.2M | if (dat->byte == oldpos) |
823 | 48 | break; |
824 | | |
825 | 13.2M | if (object_end < last_offset) |
826 | 1.12M | object_end = last_offset; |
827 | 13.2M | if (object_begin > last_offset) |
828 | 40.9k | object_begin = last_offset; |
829 | | |
830 | 13.2M | added = dwg_decode_add_object (dwg, dat, dat, last_offset); |
831 | 13.2M | if (added > 0) |
832 | 13.2M | error |= added; // else not added (skipped) or -1 for re-allocated |
833 | 13.2M | if (dwg->num_objects) |
834 | 13.1M | last_handle = dwg->object[dwg->num_objects - 1].handle.value; |
835 | | // LOG_HANDLE ("dat: @%lu.%u\n", dat->byte, dat->bit); |
836 | 13.2M | } |
837 | 28.6k | if (dat->byte == oldpos) |
838 | 48 | break; |
839 | | |
840 | | // CRC on |
841 | 28.6k | if (dat->bit > 0) |
842 | 0 | { |
843 | 0 | dat->byte += 1; |
844 | 0 | dat->bit = 0; |
845 | 0 | } |
846 | | |
847 | 28.6k | if (dat->byte >= dat->size) |
848 | 7 | { |
849 | 7 | LOG_ERROR ("Handles overflow @%" PRIuSIZE, dat->byte); |
850 | 7 | return DWG_ERR_VALUEOUTOFBOUNDS; |
851 | 7 | } |
852 | 28.6k | crc = bit_read_RS_BE (dat); |
853 | 28.6k | pvz = dat->byte; |
854 | 28.6k | LOG_TRACE ("\nHandles page crc: %04X [RSx_BE] (%" PRIuSIZE "-%" PRIuSIZE |
855 | 28.6k | " = %u)\n", |
856 | 28.6k | crc, startpos, startpos + section_size, section_size); |
857 | 28.6k | crc2 = bit_calc_CRC (0xC0C1, dat->chain + startpos, section_size); |
858 | 28.6k | if (crc != crc2) |
859 | 28.6k | { |
860 | 28.6k | LOG_ERROR ("Handles Section[%d] page CRC mismatch %04X <=> %04X", |
861 | 28.6k | (int)dwg->header.section[SECTION_HANDLES_R13].number, crc, |
862 | 28.6k | crc2); |
863 | | // fails with r14 |
864 | | // if (dwg->header.version == R_2000) |
865 | | // return DWG_ERR_WRONGCRC; |
866 | 28.6k | if (dat->from_version != R_14) |
867 | 20.1k | error |= DWG_ERR_WRONGCRC; |
868 | 28.6k | } |
869 | 28.6k | if (dat->byte >= lastmap) |
870 | 746 | break; |
871 | 28.6k | } |
872 | 27.8k | while (section_size > 2); |
873 | | |
874 | 1.20k | LOG_INFO ("Num objects: %lu\n", (unsigned long)dwg->num_objects); |
875 | 1.20k | LOG_INFO ("\n" |
876 | 1.20k | "=======> Last Object : %8lu\n", |
877 | 1.20k | (unsigned long)object_begin); |
878 | 1.20k | if (object_end <= dat->size) |
879 | 66 | dat->byte = object_end; |
880 | 1.20k | object_begin = bit_read_MS (dat); |
881 | 1.20k | LOG_TRACE ("last object size: %" PRIuSIZE " [MS]", object_begin); |
882 | 1.20k | LOG_HANDLE (" (@%" PRIuSIZE ")", object_end); |
883 | 1.20k | LOG_TRACE ("\n"); |
884 | 1.20k | LOG_INFO (" Last Object (end): %8zu\n", |
885 | 1.20k | (object_end + object_begin + 2)); |
886 | | |
887 | | /*------------------------------------------------------------------------- |
888 | | * Section 2: ObjFreeSpace, r13c3-r2000 |
889 | | */ |
890 | 1.20k | if (dwg->header.sections > 3 |
891 | 16 | && (dwg->header.section[SECTION_OBJFREESPACE_R13].address == pvz)) |
892 | 0 | { |
893 | 0 | dat->byte = dwg->header.section[SECTION_OBJFREESPACE_R13].address; |
894 | 0 | dat->bit = 0; |
895 | 0 | LOG_INFO ("\n" |
896 | 0 | "=======> ObjFreeSpace 3 (start): %4zu\n", |
897 | 0 | dat->byte); |
898 | 0 | LOG_INFO (" ObjFreeSpace 3 (end) : %4zu\n", |
899 | 0 | dat->byte |
900 | 0 | + dwg->header.section[SECTION_OBJFREESPACE_R13].size); |
901 | 0 | error |= objfreespace_private (dat, dwg); |
902 | 0 | } |
903 | | |
904 | | /*------------------------------------------------------------------------- |
905 | | * Second header, r13-r2000 only. With sentinels. |
906 | | */ |
907 | 1.20k | if (bit_search_sentinel (dat, dwg_sentinel (DWG_SENTINEL_2NDHEADER_BEGIN))) |
908 | 0 | { |
909 | 0 | struct _dwg_secondheader *_obj = &dwg->secondheader; |
910 | 0 | const char *const names[] = { |
911 | 0 | "HANDSEED", |
912 | 0 | "BLOCK_CONTROL_OBJECT", |
913 | 0 | "LAYER_CONTROL_OBJECT", |
914 | 0 | "STYLE_CONTROL_OBJECT", |
915 | 0 | "LTYPE_CONTROL_OBJECT", |
916 | 0 | "VIEW_CONTROL_OBJECT", |
917 | 0 | "UCS_CONTROL_OBJECT", |
918 | 0 | "VPORT_CONTROL_OBJECT", |
919 | 0 | "APPID_CONTROL_OBJECT", |
920 | 0 | "DIMSTYLE_CONTROL_OBJECT", |
921 | 0 | "VX_CONTROL_OBJECT", |
922 | 0 | "DICTIONARY_NAMED_OBJECT", |
923 | 0 | "DICTIONARY_ACAD_MLINESTYLE", |
924 | 0 | "DICTIONARY_ACAD_GROUP", |
925 | 0 | }; |
926 | 0 | for (int i = 0; i < ARRAY_SIZE (names); i++) |
927 | 0 | _obj->handles[i].name = names[i]; |
928 | |
|
929 | 0 | LOG_INFO ("\n=======> Second Header (start): %4zu\n", dat->byte); |
930 | 0 | error |= secondheader_private (dat, dwg); |
931 | 0 | if (bit_search_sentinel (dat, dwg_sentinel (DWG_SENTINEL_2NDHEADER_END))) |
932 | 0 | LOG_INFO (" Second Header (end) : %4zu\n", dat->byte); |
933 | 0 | } |
934 | | |
935 | | /*------------------------------------------------------------------------- |
936 | | * Section 4: Template (with MEASUREMENT) |
937 | | * (Called PADDING section in the ODA) |
938 | | */ |
939 | | |
940 | 1.20k | if (dwg->header.sections > 4) |
941 | 16 | { |
942 | 16 | LOG_INFO ("\n" |
943 | 16 | "=======> Template 4 (start) : %8u\n", |
944 | 16 | (unsigned int)dwg->header.section[4].address); |
945 | 16 | LOG_INFO (" Template 4 (end) : %8u\n", |
946 | 16 | (unsigned int)(dwg->header.section[4].address |
947 | 16 | + dwg->header.section[4].size)); |
948 | 16 | dat->byte = dwg->header.section[4].address; |
949 | 16 | dat->bit = 0; |
950 | | |
951 | 16 | error |= template_private (dat, dwg); |
952 | 16 | } |
953 | | |
954 | | // step II of handles parsing: resolve pointers from handle value |
955 | | // XXX: move this somewhere else |
956 | 1.20k | LOG_INFO ("\nnum_objects: %lu\n", (unsigned long)dwg->num_objects); |
957 | 1.20k | LOG_TRACE ("num_object_refs: %lu\n", (unsigned long)dwg->num_object_refs); |
958 | 1.20k | LOG_TRACE ("Resolving pointers from ObjectRef vector:\n"); |
959 | 1.20k | error |= resolve_objectref_vector (dat, dwg); |
960 | 1.20k | dwg_validate_entity_links (dwg); |
961 | 1.20k | return error; |
962 | 19.5k | } |
963 | | |
964 | | static int |
965 | | resolve_objectref_vector (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
966 | 1.23k | { |
967 | 1.23k | BITCODE_BL i; |
968 | 1.23k | Dwg_Object *obj; |
969 | | |
970 | 1.23k | LOG_INSANE ("==========\n"); |
971 | 582k | for (i = 0; i < dwg->num_object_refs; i++) |
972 | 580k | { |
973 | 580k | Dwg_Object_Ref *ref = dwg->object_ref[i]; |
974 | 580k | LOG_HANDLE ("-objref[%3ld]: HANDLE" FORMAT_REF "\n", (long)i, |
975 | 580k | ARGS_REF (ref)); |
976 | 580k | assert (ref->handleref.is_global == 1); |
977 | | // skip code 0 refs (e.g. HANDSEED), they are handle values, not obj refs |
978 | 580k | if (ref->handleref.code == 0) |
979 | 241k | continue; |
980 | | // search the handle in all objects |
981 | 339k | obj = dwg_resolve_handle (dwg, ref->absolute_ref); |
982 | 339k | if (obj) |
983 | 76.1k | { |
984 | 76.1k | LOG_HANDLE ("-found: HANDLE(" FORMAT_H ") => [%u]\n", |
985 | 76.1k | ARGS_H (obj->handle), obj->index); |
986 | 76.1k | } |
987 | | // assign found pointer to objectref vector |
988 | 339k | ref->obj = obj; |
989 | | #if 0 |
990 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
991 | | { |
992 | | if (obj) |
993 | | dwg_print_object (dat, obj); |
994 | | else |
995 | | LOG_HANDLE ("Null object pointer: object_ref[%ld]\n", (long)i); |
996 | | } |
997 | | #endif |
998 | 339k | } |
999 | 1.23k | dwg->dirty_refs = 0; |
1000 | 1.23k | return dwg->num_object_refs ? 0 : DWG_ERR_VALUEOUTOFBOUNDS; |
1001 | 1.23k | } |
1002 | | |
1003 | | /* Find the BITCODE_H for an object */ |
1004 | | Dwg_Object_Ref * |
1005 | | dwg_find_objectref (const Dwg_Data *restrict dwg, |
1006 | | const Dwg_Object *restrict obj) |
1007 | 0 | { |
1008 | 0 | for (BITCODE_BL i = 0; i < dwg->num_object_refs; i++) |
1009 | 0 | { |
1010 | 0 | Dwg_Object_Ref *ref = dwg->object_ref[i]; |
1011 | 0 | Dwg_Object *found = dwg_resolve_handle_silent (dwg, ref->absolute_ref); |
1012 | 0 | if (found == obj) |
1013 | 0 | return ref; |
1014 | 0 | } |
1015 | 0 | return NULL; |
1016 | 0 | } |
1017 | | |
1018 | | void |
1019 | | dwg_resolve_objectrefs_silent (Dwg_Data *restrict dwg) |
1020 | 3.59k | { |
1021 | 3.59k | const int oldloglevel = loglevel; |
1022 | 3.59k | loglevel = 0; |
1023 | | // Dwg_Object_Ref->obj are stored all over. dirty it to update dynamically. |
1024 | | // TODO: this is now forever. find a way to resolve all objs also. |
1025 | 3.59k | dwg->dirty_refs = 1; |
1026 | 19.3M | for (BITCODE_BL i = 0; i < dwg->num_object_refs; i++) |
1027 | 19.3M | { |
1028 | | // scan num_objects for the id (absolute_ref) |
1029 | 19.3M | Dwg_Object *restrict obj |
1030 | 19.3M | = dwg_resolve_handle_silent (dwg, dwg->object_ref[i]->absolute_ref); |
1031 | 19.3M | dwg->object_ref[i]->obj = obj; |
1032 | 19.3M | } |
1033 | 3.59k | dwg->dirty_refs = 0; |
1034 | | // TODO: scan dwg->num_objects also to update it's handlerefs |
1035 | 3.59k | loglevel = oldloglevel; |
1036 | 3.59k | } |
1037 | | |
1038 | | /* endian specific */ |
1039 | | void |
1040 | | bfr_read_32 (void *restrict dst, BITCODE_RC *restrict *restrict src, |
1041 | | size_t size) |
1042 | 0 | { |
1043 | 0 | size_t n; |
1044 | 0 | uint32_t *dp, *sp, *dp0 = NULL, *sp0 = NULL; |
1045 | 0 | bool dst_unaligned = false; |
1046 | 0 | bool src_unaligned = false; |
1047 | 0 | assert (!(size % 4)); |
1048 | | |
1049 | | // dst may be misaligned |
1050 | 0 | if ((intptr_t)dst % 4) |
1051 | 0 | { |
1052 | 0 | dst_unaligned = true; |
1053 | 0 | dp0 = dp = (uint32_t *)malloc (size); |
1054 | 0 | } |
1055 | 0 | else |
1056 | 0 | dp = (uint32_t *)dst; |
1057 | | // likewise *src may be misaligned |
1058 | 0 | if ((intptr_t)*src % 4) |
1059 | 0 | { |
1060 | 0 | src_unaligned = true; |
1061 | 0 | sp0 = sp = (uint32_t *)malloc (size); |
1062 | 0 | memcpy ((void *)sp, (const void *)*src, size); |
1063 | 0 | } |
1064 | 0 | else |
1065 | 0 | sp = (uint32_t *)*src; |
1066 | |
|
1067 | 0 | for (n = 0; n < size / sizeof (uint32_t); n++) |
1068 | 0 | { |
1069 | 0 | *dp++ = le32toh (*sp); |
1070 | 0 | sp++; |
1071 | 0 | } |
1072 | |
|
1073 | 0 | if (src_unaligned) |
1074 | 0 | free ((void *)sp0); |
1075 | 0 | if (dst_unaligned) |
1076 | 0 | { |
1077 | 0 | memcpy ((void *)dst, (const void *)dp0, size); |
1078 | 0 | free ((void *)dp0); |
1079 | 0 | } |
1080 | 0 | *src += size; |
1081 | 0 | size -= n * sizeof (uint32_t); |
1082 | 0 | assert (size == 0); |
1083 | 0 | } |
1084 | | |
1085 | | #if 0 |
1086 | | void |
1087 | | bfr_read (void *restrict dst, BITCODE_RC *restrict *restrict src, size_t size) |
1088 | | { |
1089 | | memcpy (dst, *src, size); |
1090 | | *src += size; |
1091 | | } |
1092 | | |
1093 | | /* endian specific */ |
1094 | | void |
1095 | | bfr_read_64 (void *restrict dst, BITCODE_RC *restrict *restrict src, |
1096 | | size_t size) |
1097 | | { |
1098 | | size_t n; |
1099 | | uint64_t *dp, *sp, *dp0 = NULL, *sp0 = NULL; |
1100 | | bool dst_unaligned = false; |
1101 | | bool src_unaligned = false; |
1102 | | assert (!(size % 8)); |
1103 | | |
1104 | | // dst may be misaligned |
1105 | | if ((intptr_t)dst % 8) |
1106 | | { |
1107 | | dst_unaligned = true; |
1108 | | dp0 = dp = (uint64_t *)malloc (size); |
1109 | | } |
1110 | | else |
1111 | | dp = (uint64_t *)dst; |
1112 | | // likewise *src may be misaligned |
1113 | | if ((intptr_t)*src % 8) |
1114 | | { |
1115 | | src_unaligned = true; |
1116 | | sp0 = sp = (uint64_t *)malloc (size); |
1117 | | memcpy ((void *)sp, (const void *)*src, size); |
1118 | | } |
1119 | | else |
1120 | | sp = (uint64_t *)src; |
1121 | | |
1122 | | for (n = 0; n < size / sizeof (uint64_t); n++) |
1123 | | { |
1124 | | *dp++ = le64toh (*sp); |
1125 | | sp++; |
1126 | | } |
1127 | | |
1128 | | if (src_unaligned) |
1129 | | free ((void *)sp0); |
1130 | | if (dst_unaligned) |
1131 | | { |
1132 | | memcpy ((void *)dst, (const void *)dp0, size); |
1133 | | free ((void *)dp0); |
1134 | | } |
1135 | | *src += size; |
1136 | | size -= n * sizeof (uint64_t); |
1137 | | assert (size == 0); |
1138 | | } |
1139 | | #endif |
1140 | | |
1141 | | // always byte-aligned |
1142 | | static unsigned char |
1143 | | copy_bytes (unsigned int lit_length, Bit_Chain *restrict src, |
1144 | | Bit_Chain *restrict dst) |
1145 | 0 | { |
1146 | 0 | LOG_INSANE (">c %u %" PRIuSIZE "->%" PRIuSIZE "\n", lit_length, src->byte, |
1147 | 0 | dst->byte); |
1148 | 0 | for (unsigned int i = 0; i < lit_length; ++i) |
1149 | 0 | { |
1150 | 0 | unsigned char b = bit_read_RC (src); |
1151 | 0 | bit_write_RC (dst, b); |
1152 | 0 | } |
1153 | 0 | return bit_read_RC (src); |
1154 | 0 | } |
1155 | | |
1156 | | /* R2004 encoded literal length |
1157 | | */ |
1158 | | static unsigned int |
1159 | | read_literal_length (Bit_Chain *restrict dat, unsigned char opcode) |
1160 | 0 | { |
1161 | 0 | unsigned int lowbits = opcode & 0xf; |
1162 | 0 | if (lowbits == 0) |
1163 | 0 | { // if low bits are 0 |
1164 | 0 | BITCODE_RC lastbyte = 0; |
1165 | 0 | while (((lastbyte = bit_read_RC (dat)) == 0) && (dat->byte < dat->size)) |
1166 | 0 | { |
1167 | 0 | LOG_INSANE ("<L %u ", lastbyte); |
1168 | 0 | lowbits += 0xFF; |
1169 | 0 | } |
1170 | 0 | lowbits += 0xf + lastbyte; |
1171 | 0 | } |
1172 | 0 | LOG_INSANE (">L %u\n", lowbits + 3); |
1173 | 0 | return lowbits + 3; |
1174 | 0 | } |
1175 | | |
1176 | | /* R2004 Read encoded number of compressed bytes |
1177 | | */ |
1178 | | static int |
1179 | | read_compressed_bytes (Bit_Chain *restrict dat, const unsigned char opcode, |
1180 | | const unsigned bits) |
1181 | 0 | { |
1182 | 0 | unsigned int compressed_bytes = opcode & bits; |
1183 | 0 | if (compressed_bytes == 0) |
1184 | 0 | { |
1185 | 0 | BITCODE_RC lastbyte = 0; |
1186 | 0 | while (((lastbyte = bit_read_RC (dat)) == 0) && (dat->byte < dat->size)) |
1187 | 0 | { |
1188 | 0 | LOG_INSANE ("<C %u\n", lastbyte); |
1189 | 0 | compressed_bytes += 0xFF; |
1190 | 0 | } |
1191 | 0 | compressed_bytes += lastbyte + bits; |
1192 | 0 | } |
1193 | 0 | LOG_INSANE (">C %u\n", compressed_bytes + 2); |
1194 | 0 | return (int)compressed_bytes + 2; |
1195 | 0 | } |
1196 | | |
1197 | | /* R2004 Two Byte Offset |
1198 | | */ |
1199 | | static BITCODE_RC |
1200 | | two_byte_offset (Bit_Chain *restrict dat, int plus, int *restrict offset) |
1201 | 0 | { |
1202 | 0 | BITCODE_RC firstByte = bit_read_RC (dat); |
1203 | 0 | BITCODE_RC secondByte = bit_read_RC (dat); |
1204 | 0 | *offset |= (firstByte >> 2); |
1205 | 0 | *offset |= secondByte << 6; |
1206 | 0 | *offset += plus; |
1207 | 0 | return firstByte; |
1208 | 0 | } |
1209 | | |
1210 | | /* Decompresses a system section of a 2004+ DWG file. |
1211 | | * With a LZ77 variant. |
1212 | | */ |
1213 | | int |
1214 | | decompress_R2004_section (Bit_Chain *restrict src, Bit_Chain *restrict dec) |
1215 | 0 | { |
1216 | 0 | unsigned int lit_length; |
1217 | 0 | int comp_offset, comp_bytes; |
1218 | 0 | size_t pos, end; |
1219 | 0 | unsigned char opcode1 = 0, opcode2; |
1220 | |
|
1221 | 0 | if (src->byte > src->size) // bytes left to read from |
1222 | 0 | { |
1223 | 0 | LOG_WARN ("Invalid comp_data_size %" PRIuSIZE " @%" PRIuSIZE, src->size, |
1224 | 0 | src->byte); |
1225 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
1226 | 0 | } |
1227 | | // length of the first sequence of uncompressed or literal data. |
1228 | | // lit_length = read_literal_length (src, opcode1); |
1229 | | // LOG_INSANE ("L: %u\n", lit_length); |
1230 | | // if ((unsigned long)lit_length > dec->size) |
1231 | | // { |
1232 | | // LOG_ERROR ("Invalid literal_length %u > %lu dec.size", lit_length, |
1233 | | // dec->size) |
1234 | | // return DWG_ERR_VALUEOUTOFBOUNDS; |
1235 | | // } |
1236 | | // bit_read_fixed (src, dec->chain, lit_length); |
1237 | | // dec->byte += lit_length; |
1238 | | // bytes_left -= lit_length; |
1239 | 0 | LOG_INSANE ("(%" PRIuSIZE ")\n", dec->byte); |
1240 | |
|
1241 | 0 | opcode1 = bit_read_RC (src); |
1242 | 0 | if ((opcode1 & 0xF0) == 0) |
1243 | 0 | opcode1 = copy_bytes (read_literal_length (src, opcode1), src, dec); |
1244 | |
|
1245 | 0 | while (src->byte < src->size && dec->byte < dec->size && opcode1 != 0x11) |
1246 | 0 | { |
1247 | 0 | LOG_INSANE ("\n(%" PRIuSIZE ") -O %x\n", dec->byte, opcode1); |
1248 | 0 | comp_bytes = 0; |
1249 | 0 | comp_offset = 0; |
1250 | 0 | if (opcode1 < 0x10 || opcode1 >= 0x40) // oda has <0x10 as unused |
1251 | 0 | { |
1252 | 0 | comp_bytes = (opcode1 >> 4) - 1; |
1253 | 0 | opcode2 = bit_read_RC (src); |
1254 | 0 | LOG_INSANE ("<O2 %x\n", opcode2); |
1255 | 0 | comp_offset = (((opcode1 >> 2) & 3) | (opcode2 << 2)) + 1; |
1256 | 0 | LOG_INSANE ("o: %d %d\n", comp_bytes, comp_offset); |
1257 | 0 | } |
1258 | 0 | else if (opcode1 < 0x20) // 0x12-0x1f |
1259 | 0 | { |
1260 | 0 | comp_bytes = read_compressed_bytes (src, opcode1, 7); |
1261 | 0 | comp_offset = (opcode1 & 8) << 11; |
1262 | 0 | opcode1 = two_byte_offset (src, 0x4000, &comp_offset); |
1263 | 0 | LOG_INSANE ("<O %x\n", opcode1); |
1264 | 0 | LOG_INSANE ("2bo: %d %d\n", comp_bytes, comp_offset); |
1265 | 0 | } |
1266 | 0 | else if (opcode1 >= 0x20) |
1267 | 0 | { |
1268 | 0 | comp_bytes = read_compressed_bytes (src, opcode1, 0x1f); |
1269 | 0 | opcode1 = two_byte_offset (src, 1, &comp_offset); |
1270 | 0 | LOG_INSANE ("<O: %x\n", opcode1); |
1271 | 0 | LOG_INSANE ("2bo: %d %d\n", comp_bytes, comp_offset); |
1272 | 0 | } |
1273 | 0 | else if (opcode1 == 0x11) |
1274 | 0 | { |
1275 | 0 | LOG_INSANE (">O %x!\n", opcode1); |
1276 | 0 | break; // Terminates the input stream, everything is ok |
1277 | 0 | } |
1278 | 0 | else |
1279 | 0 | { |
1280 | 0 | LOG_ERROR ("Invalid opcode 0x%x in input stream at pos %" PRIuSIZE, |
1281 | 0 | opcode1, src->byte); |
1282 | 0 | return DWG_ERR_INTERNALERROR; // error in input stream |
1283 | 0 | } |
1284 | | // copy previous offset'ed bytes. |
1285 | 0 | pos = dec->byte; |
1286 | 0 | LOG_INSANE ("co: %d %ld->%" PRIuSIZE "\n", comp_bytes, |
1287 | 0 | (long)pos - comp_offset, pos); |
1288 | | // A final back-reference may legitimately fill the buffer exactly to |
1289 | | // dec->size (the trailing copy lands in the unused tail past the real |
1290 | | // page data and is never read). 0.13.3 allowed this (dst + comp_bytes > |
1291 | | // dst_end); the refactor's `>=` rejected the exact-fill case and aborted |
1292 | | // the whole section mid-stream, dropping/garbling thousands of objects |
1293 | | // on real R2018 files. Only error when the copy would overrun the |
1294 | | // buffer. |
1295 | 0 | end = pos + comp_bytes; |
1296 | 0 | if (end > dec->size || (long)pos < comp_offset |
1297 | 0 | || (size_t)(pos - comp_offset) >= dec->size |
1298 | 0 | || (size_t)comp_offset > dec->size) |
1299 | 0 | { |
1300 | 0 | LOG_ERROR ("Invalid decompression bytes %d, offset %d", comp_bytes, |
1301 | 0 | comp_offset); |
1302 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
1303 | 0 | } |
1304 | | // GH #1204: memmove is wrong here: when comp_offset < comp_bytes the |
1305 | | // source and destination overlap and newly-written bytes must be read |
1306 | | // back (LZ77 run-length extension). memmove copies from original bytes. |
1307 | 0 | for (; pos < end; pos++) |
1308 | 0 | { |
1309 | 0 | #ifndef NDEBUG |
1310 | 0 | assert ((long)pos >= (long)comp_offset); |
1311 | 0 | assert (pos - comp_offset < dec->size); |
1312 | 0 | assert (pos < dec->size); |
1313 | 0 | #endif |
1314 | 0 | dec->chain[pos] = dec->chain[pos - comp_offset]; |
1315 | 0 | } |
1316 | 0 | dec->byte = end; |
1317 | | // copy "literal data" |
1318 | 0 | lit_length = opcode1 & 3; |
1319 | 0 | if (lit_length == 0) |
1320 | 0 | { |
1321 | 0 | opcode1 = bit_read_RC (src); |
1322 | 0 | LOG_INSANE ("<O %x\n", opcode1); |
1323 | 0 | if ((opcode1 & 0xf0) == 0) |
1324 | 0 | lit_length = read_literal_length (src, opcode1); |
1325 | 0 | } |
1326 | 0 | LOG_INSANE ("L %d\n", lit_length); |
1327 | 0 | if (lit_length && end + (size_t)lit_length <= dec->size) |
1328 | 0 | { |
1329 | 0 | opcode1 = copy_bytes (lit_length, src, dec); |
1330 | 0 | LOG_INSANE ("<O %x\n", opcode1); |
1331 | 0 | } |
1332 | 0 | else if (lit_length) |
1333 | 0 | break; |
1334 | 0 | } |
1335 | | #ifdef DEBUG |
1336 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
1337 | | { |
1338 | | static int ctr = 0; |
1339 | | char out[80]; |
1340 | | FILE *fp; |
1341 | | snprintf (out, 80, "decomp_%u.bin", ctr++); |
1342 | | fp = fopen (out, "wb"); |
1343 | | fwrite (dec->chain, 1, dec->size, fp); |
1344 | | fclose (fp); |
1345 | | } |
1346 | | #endif |
1347 | 0 | return 0; // Success |
1348 | 0 | } |
1349 | | |
1350 | | // index is the Section Number in the section map |
1351 | | static Dwg_Section * |
1352 | | find_section (Dwg_Data *dwg, BITCODE_RLd idx) |
1353 | 0 | { |
1354 | 0 | BITCODE_BL i; |
1355 | 0 | if (dwg->header.section == 0 || idx == 0) |
1356 | 0 | return 0; |
1357 | 0 | for (i = 0; i < dwg->header.num_sections; ++i) |
1358 | 0 | { |
1359 | 0 | if (dwg->header.section[i].number == idx) |
1360 | 0 | return &dwg->header.section[i]; |
1361 | 0 | } |
1362 | 0 | return NULL; |
1363 | 0 | } |
1364 | | |
1365 | | static int |
1366 | | add_section (Dwg_Data *dwg) |
1367 | 0 | { |
1368 | 0 | if (dwg->header.num_sections == 0) |
1369 | 0 | { |
1370 | 0 | dwg->header.section = (Dwg_Section *)calloc (1, sizeof (Dwg_Section)); |
1371 | 0 | } |
1372 | 0 | else |
1373 | 0 | { |
1374 | 0 | dwg->header.section = (Dwg_Section *)realloc ( |
1375 | 0 | dwg->header.section, |
1376 | 0 | sizeof (Dwg_Section) * (dwg->header.num_sections + 1)); |
1377 | 0 | memset (&dwg->header.section[dwg->header.num_sections], 0, |
1378 | 0 | sizeof (Dwg_Section)); |
1379 | 0 | } |
1380 | 0 | if (!dwg->header.section) |
1381 | 0 | { |
1382 | 0 | LOG_ERROR ("Out of memory"); |
1383 | 0 | return DWG_ERR_OUTOFMEM; |
1384 | 0 | } |
1385 | 0 | dwg->header.num_sections++; |
1386 | 0 | return 0; |
1387 | 0 | } |
1388 | | |
1389 | | // needed for r2004+ encode and decode (check-only) |
1390 | | // p 4.3: first calc the header with seed 0 and skipped checksum (as 0), |
1391 | | // then compress, then calc the compressed body with prev. checksum as seed. |
1392 | | // Does not advance dat->byte. |
1393 | | uint32_t |
1394 | | dwg_section_page_checksum (const uint32_t seed, Bit_Chain *restrict dat, |
1395 | | int32_t size, bool skip_checksum) |
1396 | 60.6k | { |
1397 | 60.6k | uint32_t sum1 = seed & 0xffff; |
1398 | 60.6k | uint32_t sum2 = seed >> 0x10; |
1399 | 60.6k | unsigned char *data = &dat->chain[dat->byte]; |
1400 | | // only for skip_checksum |
1401 | 60.6k | unsigned char *before = &dat->chain[dat->byte + 16]; |
1402 | 60.6k | unsigned char *after = &dat->chain[dat->byte + 20]; |
1403 | 60.6k | unsigned char *end = &dat->chain[dat->byte + size]; |
1404 | 60.6k | if (dat->byte + size > dat->size) |
1405 | 0 | { |
1406 | 0 | LOG_ERROR ("dwg_section_page_checksum size %" PRId32 " overflow", size); |
1407 | 0 | return 0; |
1408 | 0 | } |
1409 | 346k | while (size > 0 && data < end) |
1410 | 285k | { |
1411 | 285k | uint32_t chunksize = MIN (size, 0x15b0); |
1412 | 285k | size -= chunksize; |
1413 | 1.30G | for (uint32_t i = 0; i < chunksize; i++) |
1414 | 1.30G | { |
1415 | 1.30G | if (!skip_checksum || data < before || data >= after) |
1416 | 1.30G | sum1 += *data; |
1417 | | // else assume 0 for the existing checksum. mask it out |
1418 | 1.30G | sum2 += sum1; |
1419 | 1.30G | data++; |
1420 | 1.30G | } |
1421 | 285k | sum1 %= 0xFFF1; |
1422 | 285k | sum2 %= 0xFFF1; |
1423 | 285k | } |
1424 | 60.6k | return (sum2 << 0x10) | (sum1 & 0xffff); |
1425 | 60.6k | } |
1426 | | |
1427 | | /* Read R2004, 2010+ Section Map |
1428 | | * The Section Map is a vector of number, size, and address(offset) triples |
1429 | | * used to locate the sections in the file. |
1430 | | */ |
1431 | | static int |
1432 | | read_R2004_section_map (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
1433 | 0 | { |
1434 | 0 | BITCODE_RC *ptr; |
1435 | 0 | BITCODE_RLL section_address; |
1436 | 0 | long bytes_remaining; |
1437 | 0 | int i, error = 0, found_section_map_id = 0; |
1438 | 0 | Bit_Chain sec = *dat; |
1439 | 0 | Bit_Chain dec = { 0 }; |
1440 | 0 | const BITCODE_RLd section_array_size |
1441 | 0 | = dwg->fhdr.r2004_header.section_array_size; |
1442 | 0 | const BITCODE_RLL section_map_address |
1443 | 0 | = dwg->fhdr.r2004_header.section_map_address + 0x100; |
1444 | 0 | const BITCODE_RLd section_map_id = dwg->fhdr.r2004_header.section_map_id; |
1445 | 0 | BITCODE_RLd max_id = 0; |
1446 | |
|
1447 | 0 | sec.size = dwg->fhdr.r2004_header.comp_data_size + dat->byte; |
1448 | 0 | dec.size = dwg->fhdr.r2004_header.decomp_data_size; |
1449 | 0 | dec.from_version = dec.version = dat->from_version; |
1450 | 0 | dwg->header.num_sections = 0; |
1451 | 0 | dwg->header.section = 0; |
1452 | | |
1453 | | // decompressed data |
1454 | 0 | if (dec.size > 0xff000000 || // 4Gb. max_decomp_size = 0x144400 |
1455 | 0 | sec.size > dat->size) |
1456 | 0 | { |
1457 | 0 | LOG_ERROR ("Invalid r2004_header.decomp_data_size %" PRIuSIZE, dec.size); |
1458 | 0 | dwg->fhdr.r2004_header.decomp_data_size |
1459 | 0 | = 8 * (BITCODE_RL)(sec.size & 0xffffffff); |
1460 | 0 | return DWG_ERR_OUTOFMEM; |
1461 | 0 | } |
1462 | 0 | dec.chain = (BITCODE_RC *)calloc (dec.size + 1024, 1); |
1463 | 0 | if (!dec.chain) |
1464 | 0 | { |
1465 | 0 | LOG_ERROR ("Out of memory"); |
1466 | 0 | return DWG_ERR_OUTOFMEM; |
1467 | 0 | } |
1468 | | |
1469 | 0 | section_address = sec.byte; |
1470 | 0 | error = decompress_R2004_section (&sec, &dec); |
1471 | 0 | dat->byte = sec.byte; |
1472 | | #ifdef DEBUG |
1473 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
1474 | | { |
1475 | | LOG_INSANE ("dec: %" PRIuSIZE "\n", dec.size); |
1476 | | LOG_TRACE_TF (dec.chain, dec.size); |
1477 | | } |
1478 | | #endif |
1479 | 0 | if (error > DWG_ERR_CRITICAL || error == DWG_ERR_VALUEOUTOFBOUNDS) |
1480 | 0 | { |
1481 | 0 | free (dec.chain); |
1482 | 0 | return error; |
1483 | 0 | } |
1484 | 0 | LOG_TRACE ("\n#### Read 2004 Section Page Map @%x ####\n", |
1485 | 0 | (unsigned)section_map_address); |
1486 | |
|
1487 | 0 | section_address = 0x100; // starting address |
1488 | 0 | i = 0; |
1489 | 0 | bytes_remaining = (long)dec.size; |
1490 | 0 | ptr = dec.chain; |
1491 | 0 | dwg->header.num_sections = 0; |
1492 | |
|
1493 | 0 | while (bytes_remaining >= 8) |
1494 | 0 | { |
1495 | 0 | error |= add_section (dwg); |
1496 | 0 | if (error > DWG_ERR_CRITICAL) |
1497 | 0 | return error; |
1498 | | |
1499 | | // only the first two fields: number, size |
1500 | 0 | bfr_read_32 (&dwg->header.section[i], &ptr, 8); |
1501 | 0 | bytes_remaining -= 8; |
1502 | 0 | LOG_TRACE ("Section[%2d]=%2d,", i, (int)dwg->header.section[i].number); |
1503 | 0 | LOG_TRACE (" size: %5u,", (unsigned)dwg->header.section[i].size); |
1504 | 0 | dwg->header.section[i].address = section_address; |
1505 | 0 | if (dwg->header.section[i].number <= section_array_size) // GH #144 |
1506 | 0 | { |
1507 | 0 | section_address += dwg->header.section[i].size; |
1508 | 0 | LOG_TRACE (" address: 0x%04lx\n", |
1509 | 0 | (unsigned long)dwg->header.section[i].address); |
1510 | 0 | } |
1511 | 0 | else |
1512 | 0 | LOG_TRACE (" (ignored > %d section_array_size)\n", |
1513 | 0 | (int)section_array_size); |
1514 | 0 | if (dwg->header.section[i].number > max_id) |
1515 | 0 | max_id = dwg->header.section[i].number; |
1516 | | |
1517 | | // repair section_map_id.address from section_map_address |
1518 | 0 | if (dwg->header.section[i].number == section_map_id) |
1519 | 0 | { |
1520 | 0 | found_section_map_id++; |
1521 | 0 | if (dwg->header.section[i].address != section_map_address) |
1522 | 0 | { |
1523 | 0 | LOG_WARN ("Repair invalid section_map_address: %" PRIx64 |
1524 | 0 | " != %" PRIx64, |
1525 | 0 | dwg->header.section[i].address, section_map_address); |
1526 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1527 | 0 | dwg->header.section[i].address = section_map_address; |
1528 | 0 | } |
1529 | 0 | } |
1530 | 0 | if (i >= (int)section_array_size) |
1531 | 0 | { |
1532 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1533 | 0 | LOG_WARN ("Overflow section_array_size: %d >= %d (remaining: %ld)", |
1534 | 0 | i, (int)section_array_size, (long)bytes_remaining); |
1535 | 0 | if (i > 1000) |
1536 | 0 | return error; |
1537 | 0 | } |
1538 | | |
1539 | 0 | if (bytes_remaining >= 16 |
1540 | 0 | && dwg->header.section[i].number < 0) // negative: gap/unused data |
1541 | | //|| dwg->header.section[i].number > section_array_size)) |
1542 | 0 | { |
1543 | 0 | bfr_read_32 (&dwg->header.section[i].parent, &ptr, 16); |
1544 | 0 | bytes_remaining -= 16; |
1545 | 0 | LOG_TRACE (" Parent: %d, ", dwg->header.section[i].parent); |
1546 | 0 | LOG_TRACE ("Left: %d, ", dwg->header.section[i].left); |
1547 | 0 | LOG_TRACE ("Right: %d, ", dwg->header.section[i].right); |
1548 | 0 | LOG_TRACE ("0x00: %d\n", dwg->header.section[i].x00); |
1549 | 0 | } |
1550 | |
|
1551 | 0 | i++; |
1552 | 0 | } |
1553 | 0 | i--; |
1554 | 0 | free (dec.chain); |
1555 | |
|
1556 | 0 | if (max_id != section_array_size) |
1557 | 0 | { |
1558 | 0 | LOG_WARN ("Invalid section_array_size: [%u].%u != %u", i, max_id, |
1559 | 0 | (unsigned)section_array_size); |
1560 | 0 | } |
1561 | 0 | if (section_address != dwg->fhdr.r2004_header.last_section_address + 0x100) |
1562 | 0 | { |
1563 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1564 | 0 | LOG_WARN ("Invalid last_section_address: %" PRIx64 " != %" PRIx64, |
1565 | 0 | section_address, dwg->fhdr.r2004_header.last_section_address); |
1566 | 0 | } |
1567 | 0 | if (dwg->header.num_sections |
1568 | 0 | != dwg->fhdr.r2004_header.numgaps + dwg->fhdr.r2004_header.numsections) |
1569 | 0 | { |
1570 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1571 | 0 | LOG_WARN ("Invalid sections: %d != numgaps: " FORMAT_RL |
1572 | 0 | " + numsections: " FORMAT_RL, |
1573 | 0 | dwg->header.num_sections, dwg->fhdr.r2004_header.numgaps, |
1574 | 0 | dwg->fhdr.r2004_header.numsections); |
1575 | 0 | } |
1576 | 0 | if (!found_section_map_id) |
1577 | 0 | { |
1578 | 0 | BITCODE_RLx section_type; |
1579 | 0 | Dwg_Section *info; |
1580 | 0 | LOG_WARN ("section_map_id %d not found", (int)section_map_id); |
1581 | 0 | info = find_section (dwg, section_map_id); |
1582 | 0 | if (!info) |
1583 | 0 | { |
1584 | 0 | i = dwg->header.num_sections; |
1585 | 0 | add_section (dwg); |
1586 | 0 | LOG_WARN ("Add section_map_id [%d] %d => address 0x%" PRIx64, i, |
1587 | 0 | section_map_id, section_map_address); |
1588 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1589 | 0 | dwg->header.section[i].number = section_map_id; |
1590 | 0 | dwg->header.section[i].address = section_map_address; |
1591 | 0 | if (i > 0) |
1592 | 0 | dwg->header.section[i].size |
1593 | 0 | = section_map_address - dwg->header.section[i - 1].address; |
1594 | 0 | } |
1595 | 0 | info = find_section (dwg, dwg->fhdr.r2004_header.section_info_id); |
1596 | 0 | if (!info) |
1597 | 0 | goto repair_info_id; |
1598 | 0 | dat->bit = 0; |
1599 | 0 | dat->byte = info->address; |
1600 | 0 | section_type = bit_read_RL (dat); |
1601 | 0 | if (section_type != 0x4163003b) |
1602 | 0 | { |
1603 | 0 | repair_info_id: |
1604 | 0 | LOG_WARN ("Repair invalid section_info_id [%d]: => %d", i - 1, |
1605 | 0 | (int)dwg->fhdr.r2004_header.section_info_id); |
1606 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1607 | 0 | for (i = 0; i < (int)dwg->header.num_sections; ++i) |
1608 | 0 | { |
1609 | 0 | dat->bit = 0; |
1610 | 0 | dat->byte = dwg->header.section[i].address; |
1611 | 0 | if (dat->byte > dat->size) |
1612 | 0 | break; |
1613 | 0 | section_type = bit_read_RL (dat); |
1614 | 0 | if (section_type == 0x4163003b) |
1615 | 0 | { |
1616 | 0 | LOG_WARN ("Fixed section_info_id [%d]: => %d @" FORMAT_RLL, |
1617 | 0 | i, (int)dwg->fhdr.r2004_header.section_info_id, |
1618 | 0 | dwg->header.section[i].address); |
1619 | 0 | if (!info) |
1620 | 0 | info = &dwg->header.section[i]; |
1621 | 0 | info->address = dwg->header.section[i].address; |
1622 | 0 | info->size = dwg->header.section[i].size; |
1623 | 0 | info->number = dwg->fhdr.r2004_header.section_info_id; |
1624 | 0 | } |
1625 | 0 | } |
1626 | 0 | if (!info || info->number != dwg->fhdr.r2004_header.section_info_id) |
1627 | 0 | { |
1628 | 0 | i = dwg->header.num_sections; |
1629 | 0 | add_section (dwg); |
1630 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1631 | 0 | dwg->header.section[i].number |
1632 | 0 | = dwg->fhdr.r2004_header.section_info_id; |
1633 | 0 | dwg->header.section[i].address |
1634 | 0 | = dwg->header.section[i - 1].address |
1635 | 0 | + dwg->header.section[i - 1].size; |
1636 | 0 | LOG_WARN ("Add section_info_id [%d] %d => address 0x%" PRIx64, i, |
1637 | 0 | dwg->fhdr.r2004_header.section_info_id, |
1638 | 0 | dwg->header.section[i].address); |
1639 | 0 | } |
1640 | 0 | } |
1641 | 0 | } |
1642 | 0 | if (found_section_map_id > 1) |
1643 | 0 | { |
1644 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1645 | 0 | LOG_WARN ( |
1646 | 0 | "Illegal 2004 Section Page Map. Found %d section_map_id sections", |
1647 | 0 | found_section_map_id); |
1648 | 0 | } |
1649 | |
|
1650 | 0 | return error; |
1651 | 0 | } |
1652 | | |
1653 | | /* R2004+ only */ |
1654 | | unsigned int |
1655 | | section_max_decomp_size (const Dwg_Data *dwg, const Dwg_Section_Type id) |
1656 | 47.9k | { |
1657 | 47.9k | unsigned max_decomp_size = 0x7400; |
1658 | 47.9k | if (id == SECTION_APPINFOHISTORY) |
1659 | 0 | max_decomp_size = 0x1000; |
1660 | 47.9k | else if (id == SECTION_APPINFO) |
1661 | 3.68k | max_decomp_size = 0x400; // max seen 0x380 |
1662 | 44.2k | else if (id == SECTION_PREVIEW) |
1663 | 3.68k | { |
1664 | | // resp. 0x1800 with r2013+, 0x4a000 with r2007-r2010 |
1665 | 3.68k | max_decomp_size = 0x7fff; // was 0x7c00. GH #1045 |
1666 | | // if (dwg->header.version >= R_2013) |
1667 | | // max_decomp_size = 0x1800; |
1668 | | // else |
1669 | 3.68k | if (dwg->header.version >= R_2007 && dwg->header.version <= R_2010) |
1670 | 886 | max_decomp_size = 0x4a000; |
1671 | 2.79k | else if (dwg->header.version == R_2004) |
1672 | 758 | max_decomp_size = 0x144400; |
1673 | 3.68k | } |
1674 | 40.5k | else if (id == SECTION_SUMMARYINFO) |
1675 | 3.68k | max_decomp_size = 0x100; |
1676 | | |
1677 | 47.9k | return max_decomp_size; |
1678 | 47.9k | } |
1679 | | |
1680 | | /* Read R2004, 2010+ Section Info, aka 2004 Data section map |
1681 | | */ |
1682 | | static int |
1683 | | read_R2004_section_info (Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
1684 | | uint32_t comp_data_size, uint32_t decomp_data_size) |
1685 | 0 | { |
1686 | 0 | Bit_Chain dec = { 0 }; |
1687 | 0 | BITCODE_BL i, j; |
1688 | 0 | int error; |
1689 | |
|
1690 | 0 | if (decomp_data_size > 0x2f000000 && // 790Mb |
1691 | 0 | (decomp_data_size > 8 * comp_data_size || comp_data_size > dat->size)) |
1692 | 0 | { |
1693 | 0 | LOG_ERROR ("Invalid r2004_header.decomp_data_size %" PRIu32, |
1694 | 0 | decomp_data_size); |
1695 | 0 | return DWG_ERR_OUTOFMEM; |
1696 | 0 | } |
1697 | 0 | dec.size = decomp_data_size; |
1698 | 0 | dec.chain |
1699 | 0 | = (BITCODE_RC *)calloc (decomp_data_size + 1024, sizeof (BITCODE_RC)); |
1700 | 0 | if (!dec.chain) |
1701 | 0 | { |
1702 | 0 | LOG_ERROR ("Out of memory"); |
1703 | 0 | return DWG_ERR_OUTOFMEM; |
1704 | 0 | } |
1705 | | |
1706 | 0 | error = decompress_R2004_section (dat, &dec); |
1707 | 0 | if (error > DWG_ERR_CRITICAL || error == DWG_ERR_VALUEOUTOFBOUNDS) |
1708 | 0 | { |
1709 | 0 | free (dec.chain); |
1710 | 0 | return error; |
1711 | 0 | } |
1712 | 0 | dec.byte = 0; |
1713 | 0 | LOG_TRACE ("\n#### Read 2004 section_infohdr ####\n"); |
1714 | 0 | { |
1715 | 0 | Dwg_Object *obj = NULL; |
1716 | 0 | Dwg_Section_InfoHdr *_obj = &dwg->header.section_infohdr; |
1717 | 0 | dat = &dec; |
1718 | 0 | FIELD_RL (num_desc, 0); |
1719 | 0 | FIELD_RL (compressed, 0); |
1720 | 0 | FIELD_RLx (max_size, 0); |
1721 | 0 | FIELD_RL (encrypted, 0); |
1722 | 0 | FIELD_RL (num_desc2, 0); |
1723 | | // dwg->header.section_infohdr.num_desc = bit_read_RL (&dec); |
1724 | | // LOG_TRACE ("num_desc: %d\n", dwg->header.section_infohdr.num_desc); |
1725 | | // dwg->header.section_infohdr.compressed = bit_read_RL (&dec); |
1726 | | // LOG_TRACE ("compressed: %d\n", dwg->header.section_infohdr.compressed); |
1727 | | // dwg->header.section_infohdr.max_size = bit_read_RL (&dec); |
1728 | | // LOG_TRACE ("max_size: 0x%x\n", dwg->header.section_infohdr.max_size); |
1729 | | // dwg->header.section_infohdr.encrypted = bit_read_RL (&dec); |
1730 | | // LOG_TRACE ("encrypted: %d\n", dwg->header.section_infohdr.encrypted); |
1731 | | // dwg->header.section_infohdr.num_desc2 = bit_read_RL (&dec); |
1732 | | // LOG_TRACE ("num_desc2: %d/0x%x\n", |
1733 | | // dwg->header.section_infohdr.num_desc2, |
1734 | | // dwg->header.section_infohdr.num_desc2) |
1735 | 0 | } |
1736 | 0 | assert (dec.byte == 20); |
1737 | |
|
1738 | 0 | if (dwg->header.section_infohdr.num_desc |
1739 | 0 | > 0xc0000000 / sizeof (Dwg_Section_Info)) |
1740 | 0 | { |
1741 | 0 | LOG_ERROR ("Illegal num_desc"); |
1742 | 0 | free (dec.chain); |
1743 | 0 | dwg->header.section_infohdr.num_desc = 0; |
1744 | 0 | dwg->header.section_infohdr.num_desc2 = 0; |
1745 | 0 | return error | DWG_ERR_INVALIDDWG; |
1746 | 0 | } |
1747 | 0 | dwg->header.section_info = (Dwg_Section_Info *)calloc ( |
1748 | 0 | dwg->header.section_infohdr.num_desc, sizeof (Dwg_Section_Info)); |
1749 | 0 | if (!dwg->header.section_info) |
1750 | 0 | { |
1751 | 0 | LOG_ERROR ("Out of memory"); |
1752 | 0 | return error | DWG_ERR_OUTOFMEM; |
1753 | 0 | } |
1754 | | // decomp_end = decomp + decomp_data_size + 1024; |
1755 | 0 | for (i = 0; i < dwg->header.section_infohdr.num_desc; ++i) |
1756 | 0 | { |
1757 | 0 | Dwg_Section_Info *info; |
1758 | | // uint64_t sum_decomp = 0; |
1759 | 0 | uint64_t prev_address = 0; |
1760 | 0 | unsigned max_decomp_size; |
1761 | |
|
1762 | 0 | if (dec.byte + 8 + 6 * 4 + 64 >= dec.size) |
1763 | 0 | { |
1764 | 0 | free (dec.chain); |
1765 | 0 | dwg->header.section_infohdr.num_desc = i; |
1766 | 0 | LOG_ERROR ("read_R2004_section_info out of range"); |
1767 | 0 | return DWG_ERR_INVALIDDWG; |
1768 | 0 | } |
1769 | 0 | { |
1770 | 0 | Dwg_Object *obj = NULL; |
1771 | 0 | Dwg_Section_Info *_obj = &dwg->header.section_info[i]; |
1772 | 0 | info = _obj; |
1773 | 0 | LOG_TRACE ("\nsection_info[%d] fields:\n", i); |
1774 | 0 | FIELD_RLL (size, 0); |
1775 | 0 | FIELD_RL (num_sections, 0); |
1776 | 0 | FIELD_RLx (max_decomp_size, 0); // normally 0x7400, max 0x8000 |
1777 | 0 | FIELD_RL (unknown, 0); |
1778 | 0 | FIELD_RL (compressed, 0); // 1=no, 2=yes |
1779 | 0 | FIELD_RL (type, 0); |
1780 | 0 | FIELD_RL (encrypted, 0); // 0=no, 1=yes, 2=unknown |
1781 | 0 | bit_read_fixed (&dec, (BITCODE_RC *)info->name, 64); |
1782 | 0 | LOG_TRACE ("name: \"%s\"\n", info->name); |
1783 | | // FIELD_TFF (name, 64, 0); |
1784 | 0 | info->fixedtype = dwg_section_type (info->name); |
1785 | 0 | LOG_TRACE ("fixedtype: %d\n\n", info->fixedtype); |
1786 | 0 | } |
1787 | | |
1788 | | // if (dec.byte >= dec.size) |
1789 | | // { |
1790 | | // info->name[0] = '\0'; |
1791 | | // info->num_sections = 0; |
1792 | | // info->sections = NULL; |
1793 | | // dwg->header.section_infohdr.num_desc = i; |
1794 | | // free (dec.chain); |
1795 | | // LOG_ERROR ("read_R2004_section_info out of range"); |
1796 | | // return DWG_ERR_INVALIDDWG; |
1797 | | // } |
1798 | | // max_decomp_size is the decompressed block size |
1799 | 0 | max_decomp_size = section_max_decomp_size (dwg, info->fixedtype); |
1800 | 0 | if (info->max_decomp_size > max_decomp_size) |
1801 | 0 | { |
1802 | 0 | LOG_ERROR ("Skip section %s with max decompression size 0x%x > 0x%x", |
1803 | 0 | info->name, info->max_decomp_size, max_decomp_size); |
1804 | 0 | info->max_decomp_size = info->size = 0; |
1805 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1806 | 0 | } |
1807 | 0 | if (info->num_sections < 1000000) |
1808 | 0 | { |
1809 | | // bug in Teigha with Template, with num_sections=0 |
1810 | | /* |
1811 | | int32_t old_section_number = 0; |
1812 | | if (info->num_sections == 0 |
1813 | | && info->fixedtype == SECTION_TEMPLATE |
1814 | | // && is_teigha |
1815 | | && info->size >= 4) |
1816 | | { |
1817 | | LOG_INFO ("Fixup TEMPLATE.num_sections to 1 (Teigha bug)\n"); |
1818 | | info->num_sections = 1; |
1819 | | } |
1820 | | */ |
1821 | | /* |
1822 | | if (info->size > (int64_t)info->num_sections |
1823 | | * (int64_t)info->max_decomp_size * 2L) |
1824 | | { |
1825 | | LOG_ERROR ("Skip section %s with size %" PRId64 " > " FORMAT_RL |
1826 | | " * " FORMAT_RL, |
1827 | | info->name, info->size, info->num_sections, |
1828 | | info->max_decomp_size); |
1829 | | info->max_decomp_size = info->size = info->num_sections = 0; |
1830 | | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1831 | | } |
1832 | | */ |
1833 | 0 | if (info->num_sections > 1 && info->size < info->max_decomp_size) |
1834 | 0 | { |
1835 | | // on mult. blocks, size must exceed the size of the first block |
1836 | 0 | LOG_ERROR ("Skip section %s(%u) with size %" PRId64 |
1837 | 0 | " < max_decomp_size " FORMAT_RL, |
1838 | 0 | info->name, info->type, info->size, |
1839 | 0 | info->max_decomp_size); |
1840 | 0 | info->max_decomp_size = info->size = info->num_sections = 0; |
1841 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
1842 | 0 | } |
1843 | 0 | LOG_INFO ("Page count %u in area %d\n", info->num_sections, i); |
1844 | 0 | free (info->sections); |
1845 | 0 | info->sections = (Dwg_Section **)calloc (info->num_sections, |
1846 | 0 | sizeof (Dwg_Section *)); |
1847 | 0 | if (!info->sections) |
1848 | 0 | { |
1849 | 0 | free (dec.chain); |
1850 | 0 | LOG_ERROR ("Out of memory with %u sections", info->num_sections); |
1851 | 0 | return error | DWG_ERR_OUTOFMEM; |
1852 | 0 | } |
1853 | 0 | prev_address = 0; |
1854 | |
|
1855 | 0 | for (j = 0; j < info->num_sections; j++) |
1856 | 0 | { |
1857 | 0 | struct _section_page |
1858 | 0 | { |
1859 | 0 | int32_t number; |
1860 | 0 | uint32_t size; |
1861 | 0 | uint64_t address; |
1862 | 0 | } page; |
1863 | |
|
1864 | 0 | if (dec.byte + 16 > dec.size) |
1865 | 0 | { |
1866 | 0 | LOG_ERROR ("read_R2004_section_info[%u] out of range " |
1867 | 0 | "%zu/%zu, abort", |
1868 | 0 | j, dec.byte, dec.size); |
1869 | 0 | info->num_sections = j; |
1870 | 0 | error |= DWG_ERR_SECTIONNOTFOUND; |
1871 | 0 | break; |
1872 | 0 | } |
1873 | | /* endian specific code: */ |
1874 | 0 | page.number = bit_read_RL (&dec); |
1875 | 0 | page.size = bit_read_RL (&dec); |
1876 | 0 | page.address = bit_read_RLL (&dec); |
1877 | | // sum_decomp += page.size; /* TODO: uncompressed size */ |
1878 | | #if 0 |
1879 | | if (page.address < sum_decomp) |
1880 | | { |
1881 | | /* ODA: "If the start offset is smaller than the sum of the decompressed |
1882 | | * size of all previous pages, then this page is to be preceded by |
1883 | | * zero pages until this condition is met. */ |
1884 | | LOG_WARN ("address %lu < sum_decomp %lu", page.address, sum_decomp); |
1885 | | } |
1886 | | #endif |
1887 | 0 | info->sections[j] = find_section (dwg, page.number); |
1888 | 0 | if (info->sections[j]) |
1889 | 0 | { |
1890 | 0 | LOG_HANDLE (" section[%d].info[%d]: %s type %d => ", i, |
1891 | 0 | j, info->name, info->sections[j]->type); |
1892 | 0 | info->sections[j]->type = info->fixedtype; |
1893 | 0 | LOG_HANDLE ("type %d\n", info->sections[j]->type); |
1894 | 0 | } |
1895 | |
|
1896 | 0 | if (page.number < 0) |
1897 | 0 | { // gap/unused data |
1898 | 0 | LOG_TRACE ("Page: %4" PRId32 " (-)", page.number); |
1899 | 0 | info->num_sections++; |
1900 | 0 | info->sections = (Dwg_Section **)realloc ( |
1901 | 0 | info->sections, |
1902 | 0 | info->num_sections * sizeof (Dwg_Section *)); |
1903 | 0 | info->sections[info->num_sections - 1] = NULL; |
1904 | 0 | } |
1905 | 0 | else if (page.address < prev_address) |
1906 | 0 | { |
1907 | 0 | LOG_TRACE ("Page: %4" PRId32 " (a)", page.number); |
1908 | 0 | } |
1909 | 0 | else if (info->sections[0] |
1910 | 0 | && page.number > (int32_t)(info->num_sections |
1911 | 0 | + info->sections[0]->number)) |
1912 | 0 | { |
1913 | | // for [7] ptr+160 seems to be AcDb:ObjFreeSpace |
1914 | 0 | LOG_TRACE ("Page: %4" PRId32 " (n)", page.number); |
1915 | 0 | } |
1916 | | /* |
1917 | | else if (!info->sections[j] |
1918 | | && page.number != old_section_number + 1) |
1919 | | { |
1920 | | LOG_WARN ("Page: %4" PRId32 " (b)", page.number); |
1921 | | LOG_TRACE (" size: %5" PRIu32, page.size) // compressed |
1922 | | LOG_TRACE (" address: 0x%" PRIx64, page.address); |
1923 | | if (info->sections[j]) |
1924 | | LOG_TRACE (" info: 0x%" PRIx64, |
1925 | | info->sections[j]->address); |
1926 | | LOG_TRACE ("\n"); |
1927 | | dec.byte -= 16; |
1928 | | break; |
1929 | | } |
1930 | | */ |
1931 | 0 | else |
1932 | 0 | { |
1933 | 0 | LOG_TRACE ("Page: %4" PRId32 " ", page.number); |
1934 | | // old_section_number = page.number; |
1935 | 0 | prev_address = page.address; |
1936 | 0 | } |
1937 | 0 | LOG_TRACE (" size: %5" PRIu32, page.size); // compressed |
1938 | 0 | LOG_TRACE (" address: 0x%" PRIx64, page.address); |
1939 | 0 | if (info->sections[j]) |
1940 | 0 | LOG_TRACE (" info: 0x%" PRIx64, info->sections[j]->address); |
1941 | 0 | LOG_TRACE ("\n"); |
1942 | 0 | } |
1943 | 0 | } |
1944 | 0 | else |
1945 | 0 | { |
1946 | 0 | LOG_ERROR ("Section count %u in area %d too high! Skipping", |
1947 | 0 | info->num_sections, i); |
1948 | 0 | info->num_sections = 0; |
1949 | 0 | free (dec.chain); |
1950 | 0 | return error | DWG_ERR_VALUEOUTOFBOUNDS; |
1951 | 0 | } |
1952 | 0 | } |
1953 | 0 | free (dec.chain); |
1954 | 0 | return error; |
1955 | 0 | } |
1956 | | |
1957 | | /* Encrypted Section Header */ |
1958 | | #pragma pack(push) |
1959 | | #pragma pack(1) |
1960 | | typedef union _encrypted_section_header |
1961 | | { |
1962 | | uint32_t long_data[8]; |
1963 | | struct |
1964 | | { |
1965 | | uint32_t page_type; // always 0x4163043b |
1966 | | uint32_t section_type; // see dwg_section_type() |
1967 | | uint32_t data_size; // compressed |
1968 | | uint32_t page_size; // decompressed |
1969 | | uint32_t address; // start offset into page_size |
1970 | | uint32_t unknown; // oda writes 0 |
1971 | | uint32_t page_header_crc; // section page checksum from unencoded header |
1972 | | uint32_t data_crc; // from compressed data |
1973 | | } fields; |
1974 | | } encrypted_section_header; |
1975 | | #pragma pack(pop) |
1976 | | |
1977 | | static int |
1978 | | read_2004_compressed_section (Bit_Chain *dat, Dwg_Data *restrict dwg, |
1979 | | Bit_Chain *sec_dat, Dwg_Section_Type type) |
1980 | 0 | { |
1981 | 0 | uint32_t max_decomp_size; |
1982 | 0 | long bytes_left; |
1983 | 0 | Dwg_Section_Info *info = NULL; |
1984 | 0 | encrypted_section_header es; |
1985 | 0 | Bit_Chain dec = { 0 }; |
1986 | 0 | BITCODE_BL i, j; |
1987 | 0 | int error = 0; |
1988 | |
|
1989 | 0 | for (i = 0; i < dwg->header.section_infohdr.num_desc && !info; ++i) |
1990 | 0 | { |
1991 | 0 | if (dwg->header.section_info[i].fixedtype == type) |
1992 | 0 | { |
1993 | 0 | info = &dwg->header.section_info[i]; |
1994 | 0 | break; |
1995 | 0 | } |
1996 | 0 | } |
1997 | 0 | if (!info) |
1998 | 0 | { |
1999 | 0 | if (type < SECTION_REVHISTORY && type != SECTION_TEMPLATE |
2000 | 0 | && type != SECTION_OBJFREESPACE) |
2001 | 0 | { |
2002 | 0 | LOG_WARN ("Failed to find section_info[%u] with type %d", i, type); |
2003 | 0 | return DWG_ERR_SECTIONNOTFOUND; |
2004 | 0 | } |
2005 | 0 | else |
2006 | 0 | { |
2007 | 0 | LOG_TRACE ("Found no section_info[%u] with type %d\n", i, type); |
2008 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
2009 | 0 | } |
2010 | 0 | } |
2011 | 0 | else |
2012 | 0 | { |
2013 | 0 | LOG_TRACE ("\nFound section_info[" FORMAT_BL |
2014 | 0 | "] %s type %d with %d sections (%scompressed):\n", |
2015 | 0 | i, info->name, type, info->num_sections, |
2016 | 0 | info->compressed == 2 ? "" : "un"); |
2017 | 0 | } |
2018 | 0 | if (info->num_sections == 0) |
2019 | 0 | { |
2020 | | // XXX: This Teigha bug is already fixed up before |
2021 | 0 | if (type == SECTION_TEMPLATE && is_teigha && info->size >= 4 |
2022 | 0 | && info->unknown == 1) |
2023 | 0 | { |
2024 | 0 | Dwg_Section *sec = calloc (1, sizeof (Dwg_Section)); |
2025 | | // bug in Teigha with Template, with num_sections=0 |
2026 | 0 | info->num_sections = 1; |
2027 | 0 | info->sections = realloc (info->sections, sizeof (Dwg_Section *)); |
2028 | 0 | if (!info->sections || !sec) |
2029 | 0 | return DWG_ERR_OUTOFMEM; |
2030 | 0 | else |
2031 | 0 | info->sections[0] = sec; |
2032 | 0 | } |
2033 | | /* |
2034 | | else if (type == SECTION_UNKNOWN) |
2035 | | { |
2036 | | Dwg_Section *sec = calloc (1, sizeof (Dwg_Section)); |
2037 | | info->num_sections = 1; // hidden. enable it |
2038 | | info->size = 128; |
2039 | | sec->type = SECTION_UNKNOWN; |
2040 | | sec->compression_type = info->compressed; |
2041 | | sec->address = 128; |
2042 | | sec->size = 128; |
2043 | | if (info->sections) // [0] is NULL anyway |
2044 | | free (info->sections); |
2045 | | info->sections = calloc (1, sizeof (Dwg_Section*)); |
2046 | | info->sections[0] = sec; |
2047 | | } |
2048 | | */ |
2049 | 0 | else |
2050 | 0 | return 0; |
2051 | 0 | } |
2052 | 0 | if (!info->sections) |
2053 | 0 | { |
2054 | 0 | LOG_ERROR ("Empty sections for %s", info->name); |
2055 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
2056 | 0 | } |
2057 | | // Compute in 64-bit: both factors are uint32 (BITCODE_RL), so the product |
2058 | | // overflows the uint32_t max_decomp_size and wraps to a small value, letting |
2059 | | // the guard below pass while info->size (checked as int64 at :2059) stays |
2060 | | // large -> under-allocation and a later OOB sentinel scan. GH security. |
2061 | 0 | { |
2062 | 0 | uint64_t max_decomp_size64 |
2063 | 0 | = (uint64_t)info->num_sections * (uint64_t)info->max_decomp_size; |
2064 | 0 | if (max_decomp_size64 == 0 || max_decomp_size64 > 0x2f000000) // 790Mb |
2065 | 0 | { |
2066 | 0 | LOG_ERROR ("Invalid section %s count or max decompression size. " |
2067 | 0 | "Sections: " FORMAT_RL ", Max size: " FORMAT_RL, |
2068 | 0 | info->name, info->num_sections, info->max_decomp_size); |
2069 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
2070 | 0 | } |
2071 | 0 | max_decomp_size = (uint32_t)max_decomp_size64; |
2072 | 0 | } |
2073 | 0 | if (info->size > (int64_t)info->num_sections * (int64_t)info->max_decomp_size |
2074 | 0 | || info->size < 0) |
2075 | 0 | { |
2076 | 0 | LOG_ERROR ("Invalid section %s size %" PRId64 " > %u * " FORMAT_RL, |
2077 | 0 | info->name, info->size, info->num_sections, |
2078 | 0 | info->max_decomp_size); |
2079 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
2080 | 0 | } |
2081 | 0 | LOG_HANDLE ("Alloc section %s size %" PRIu32 "\n", info->name, |
2082 | 0 | max_decomp_size); |
2083 | 0 | dec.opts = dwg->opts & DWG_OPTS_LOGLEVEL; |
2084 | 0 | dec.size = max_decomp_size; |
2085 | 0 | dec.version = dat->version; |
2086 | 0 | dec.from_version = dat->from_version; |
2087 | 0 | dec.chain = (BITCODE_RC *)calloc (max_decomp_size, 1); |
2088 | 0 | if (!dec.chain) |
2089 | 0 | { |
2090 | 0 | LOG_ERROR ("Out of memory with " FORMAT_RL |
2091 | 0 | " sections of size: " FORMAT_RL, |
2092 | 0 | info->num_sections, info->max_decomp_size); |
2093 | 0 | return DWG_ERR_OUTOFMEM; |
2094 | 0 | } |
2095 | 0 | bytes_left = max_decomp_size; |
2096 | 0 | sec_dat->bit = 0; |
2097 | 0 | sec_dat->byte = 0; |
2098 | 0 | sec_dat->version = dat->version; |
2099 | 0 | sec_dat->from_version = dat->from_version; |
2100 | 0 | sec_dat->chain = dec.chain; |
2101 | 0 | sec_dat->size = 0; |
2102 | |
|
2103 | 0 | for (i = j = 0; i < info->num_sections; ++i, ++j) |
2104 | 0 | { |
2105 | 0 | uint32_t address, sec_mask; |
2106 | 0 | if (!info->sections[i]) |
2107 | 0 | { |
2108 | 0 | LOG_WARN ("Skip empty section %u %s", i, info->name); |
2109 | 0 | if (i == info->num_sections - 1) // the last one |
2110 | 0 | { |
2111 | 0 | free (dec.chain); |
2112 | 0 | sec_dat->chain = NULL; |
2113 | 0 | return DWG_ERR_SECTIONNOTFOUND; |
2114 | 0 | } |
2115 | 0 | j--; // index for writing info->max_decomp_size chunks |
2116 | 0 | continue; |
2117 | 0 | } |
2118 | 0 | address = info->sections[i]->address; |
2119 | 0 | if (address + 32 > dat->size) |
2120 | 0 | { |
2121 | 0 | LOG_ERROR ("Section %s address %u + 32 > %" PRIuSIZE, info->name, |
2122 | 0 | address, dat->size); |
2123 | 0 | free (dec.chain); |
2124 | 0 | sec_dat->chain = NULL; |
2125 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
2126 | 0 | } |
2127 | 0 | memcpy (es.long_data, &dat->chain[address], 32); |
2128 | 0 | dat->byte = address + 32; |
2129 | | // bit_read_fixed (dat, es.char_data, 32); |
2130 | | |
2131 | | //? if encrypted properties: security_type & 2 ?? |
2132 | 0 | sec_mask = htole32 (0x4164536b ^ address); |
2133 | 0 | { |
2134 | 0 | for (int k = 0; k < 8; ++k) |
2135 | 0 | es.long_data[k] = le32toh (es.long_data[k] ^ sec_mask); |
2136 | 0 | } |
2137 | |
|
2138 | 0 | LOG_INFO ("=== Section %s (%u) @%u ===\n", info->name, i, address); |
2139 | 0 | if (es.fields.page_type != 0x4163043b) |
2140 | 0 | LOG_WARN ("page_type: 0x%x (should be 0x4163043b)", |
2141 | 0 | (unsigned)es.fields.page_type); |
2142 | 0 | else |
2143 | 0 | LOG_INFO ("page_type: 0x%x\n", (unsigned)es.fields.page_type); |
2144 | 0 | LOG_INFO ("Section Type: %u\n", (unsigned)es.fields.section_type); |
2145 | | // this is the number of bytes that is read in decompress_R2004_section |
2146 | | // (+ 2bytes) |
2147 | 0 | LOG_INFO ("Data size: 0x%x/%u (compressed)\n", |
2148 | 0 | (unsigned)es.fields.data_size, (unsigned)es.fields.data_size); |
2149 | 0 | LOG_INFO ("Page size: 0x%x/%u (decompressed)\n", |
2150 | 0 | (unsigned)es.fields.page_size, (unsigned)es.fields.page_size); |
2151 | 0 | LOG_TRACE ("StartOffset: 0x%x/%u\n", (unsigned)es.fields.address, |
2152 | 0 | (unsigned)es.fields.address); |
2153 | 0 | LOG_HANDLE ("Unknown: 0x%x\n", (unsigned)es.fields.unknown); |
2154 | 0 | LOG_HANDLE ("page_header_crc: 0x%X\n", |
2155 | 0 | (unsigned)es.fields.page_header_crc); |
2156 | 0 | LOG_HANDLE ("data_crc: 0x%X\n", (unsigned)es.fields.data_crc); |
2157 | 0 | LOG_TRACE ("Section start: %" PRIuSIZE "\n\n", dat->byte); |
2158 | | |
2159 | | // GH #126 part 4 |
2160 | 0 | LOG_INSANE ("info[%d]->max_decomp_size: %" PRIu32 " (0x%" PRIx32 ")\n", |
2161 | 0 | i, info->max_decomp_size, info->max_decomp_size); |
2162 | 0 | LOG_INSANE ("max_decomp_size: %" PRIu32 " (0x%" PRIx32 ")\n", |
2163 | 0 | max_decomp_size, max_decomp_size); |
2164 | 0 | LOG_INSANE ("bytes_left: %ld\n", bytes_left); |
2165 | | |
2166 | | // check if compressed at all |
2167 | 0 | if (info->compressed == 2 && bytes_left > 0 |
2168 | 0 | && es.fields.address <= max_decomp_size |
2169 | 0 | && es.fields.address + info->max_decomp_size <= max_decomp_size) |
2170 | 0 | { |
2171 | 0 | size_t orig_size = dat->size; |
2172 | 0 | dec.byte = es.fields.address; |
2173 | | /* == j * info->max_decomp_size;*/ // offset |
2174 | 0 | LOG_INSANE ("dec offset: %" PRIuSIZE "\n", dec.byte); |
2175 | | /* dec.size stays pinned to max_decomp_size (the true allocation). |
2176 | | Overwriting it here with a smaller per-section value causes |
2177 | | bit_chain_alloc to realloc the buffer to a smaller size, then |
2178 | | dec.byte and dec.size drift past the shrunk allocation resulting |
2179 | | in a heap-buffer-overflow WRITE (GHSA-qg2f-8389-w95j). The |
2180 | | pre-loop guard already ensures address+max_decomp_size <= |
2181 | | max_decomp_size, so the decompress bounds check is still valid. */ |
2182 | 0 | LOG_INSANE ("dec size: %" PRIuSIZE "\n", dec.size); |
2183 | 0 | dat->size = dat->byte + es.fields.data_size; |
2184 | 0 | if (dat->size > orig_size) |
2185 | 0 | { |
2186 | 0 | LOG_ERROR ("Compressed section data_size overflow"); |
2187 | 0 | dat->size = orig_size; |
2188 | 0 | } |
2189 | | #ifdef DEBUG |
2190 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
2191 | | { |
2192 | | if (type == SECTION_AUXHEADER) |
2193 | | { |
2194 | | FILE *fp = fopen ("comp_auxh.bin", "wb"); |
2195 | | fwrite (&dat->chain[dat->byte], 1, es.fields.data_size, fp); |
2196 | | fclose (fp); |
2197 | | } |
2198 | | else if (type == SECTION_OBJFREESPACE) |
2199 | | { |
2200 | | FILE *fp = fopen ("comp_ofs.bin", "wb"); |
2201 | | fwrite (&dat->chain[dat->byte], 1, es.fields.data_size, fp); |
2202 | | fclose (fp); |
2203 | | } |
2204 | | } |
2205 | | #endif |
2206 | 0 | error = decompress_R2004_section (dat, &dec); |
2207 | 0 | sec_dat->chain = dec.chain; // may be realloced |
2208 | 0 | dat->size = orig_size; |
2209 | 0 | if (error > DWG_ERR_CRITICAL) |
2210 | 0 | { |
2211 | 0 | free (dec.chain); |
2212 | 0 | sec_dat->chain = NULL; |
2213 | 0 | return error; |
2214 | 0 | } |
2215 | 0 | bytes_left -= info->max_decomp_size; |
2216 | 0 | sec_dat->size += info->max_decomp_size; |
2217 | 0 | } |
2218 | 0 | else |
2219 | 0 | { |
2220 | 0 | const size_t offset = address + 32; |
2221 | 0 | const BITCODE_RL size |
2222 | 0 | = MIN ((BITCODE_RL)(info->size - es.fields.address), |
2223 | 0 | es.fields.page_size); |
2224 | 0 | if (info->compressed == 2 || bytes_left < 0 |
2225 | 0 | || es.fields.address > max_decomp_size |
2226 | 0 | || es.fields.address + size > max_decomp_size |
2227 | 0 | || es.fields.address + size > dec.size |
2228 | 0 | || offset + size > dat->size) |
2229 | 0 | { |
2230 | 0 | LOG_ERROR ("Some section size or address out of bounds"); |
2231 | 0 | free (dec.chain); |
2232 | 0 | sec_dat->chain = NULL; |
2233 | 0 | return type < SECTION_REVHISTORY ? DWG_ERR_INVALIDDWG |
2234 | 0 | : DWG_ERR_VALUEOUTOFBOUNDS; |
2235 | 0 | } |
2236 | 0 | assert (j < info->num_sections); |
2237 | 0 | memcpy (&dec.chain[es.fields.address], &dat->chain[offset], size); |
2238 | 0 | bytes_left -= size; |
2239 | 0 | sec_dat->size += size; |
2240 | 0 | } |
2241 | 0 | } |
2242 | 0 | sec_dat->size = info->size; |
2243 | 0 | return error; |
2244 | 0 | } |
2245 | | |
2246 | | /* R2004, 2010+ Class Section |
2247 | | */ |
2248 | | static int |
2249 | | read_2004_section_classes (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2250 | 0 | { |
2251 | 0 | BITCODE_RL size; |
2252 | 0 | BITCODE_BS max_num, i; |
2253 | 0 | char c; |
2254 | 0 | int error; |
2255 | 0 | Bit_Chain sec_dat = { 0 }, str_dat = { 0 }; |
2256 | 0 | Dwg_Object *obj = NULL; |
2257 | |
|
2258 | 0 | memset (&sec_dat, 0, sizeof (sec_dat)); |
2259 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_CLASSES); |
2260 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
2261 | 0 | { |
2262 | 0 | LOG_ERROR ("Failed to read compressed %s section", "Classes"); |
2263 | 0 | if (sec_dat.chain) |
2264 | 0 | free (sec_dat.chain); |
2265 | 0 | return error; |
2266 | 0 | } |
2267 | | #ifdef DEBUG |
2268 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
2269 | | { |
2270 | | FILE *fp = fopen ("decomp_cls.bin", "wb"); |
2271 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
2272 | | fclose (fp); |
2273 | | } |
2274 | | #endif |
2275 | | |
2276 | 0 | if (bit_search_sentinel (&sec_dat, dwg_sentinel (DWG_SENTINEL_CLASS_BEGIN))) |
2277 | 0 | { |
2278 | 0 | BITCODE_RL bitsize = 0; |
2279 | 0 | LOG_TRACE ("\nClasses\n-------------------\n"); |
2280 | 0 | size = bit_read_RL (&sec_dat); // size of class data area |
2281 | 0 | LOG_TRACE ("size: " FORMAT_RL " [RL]\n", size); |
2282 | 0 | if ((dat->from_version >= R_2010 && dwg->header.maint_version > 3) |
2283 | 0 | || dat->from_version >= R_2018) |
2284 | 0 | { |
2285 | 0 | BITCODE_RL hsize = bit_read_RL (&sec_dat); |
2286 | 0 | LOG_TRACE ("hsize: " FORMAT_RL " [RL]\n", hsize); |
2287 | 0 | } |
2288 | 0 | if (dat->from_version >= R_2007) |
2289 | 0 | { |
2290 | 0 | bitsize = bit_read_RL (&sec_dat); |
2291 | 0 | LOG_TRACE ("bitsize: " FORMAT_RL " [RL]\n", bitsize); |
2292 | 0 | } |
2293 | 0 | max_num = bit_read_BS (&sec_dat); // Maximum class number |
2294 | 0 | LOG_TRACE ("max_num: " FORMAT_BS " [BS]\n", max_num); |
2295 | | // or just a single RS (always 0) |
2296 | 0 | c = bit_read_RC (&sec_dat); // 0x00 |
2297 | 0 | LOG_HANDLE ("c: " FORMAT_RC " [RC]\n", c); |
2298 | 0 | c = bit_read_RC (&sec_dat); // 0x00 |
2299 | 0 | LOG_HANDLE ("c: " FORMAT_RC " [RC]\n", c); |
2300 | 0 | c = bit_read_B (&sec_dat); // 1 |
2301 | 0 | LOG_HANDLE ("b: " FORMAT_B " [B]\n", c); |
2302 | |
|
2303 | 0 | dwg->layout_type = 0; |
2304 | 0 | dwg->num_classes = max_num - 499; |
2305 | 0 | if (max_num < 500 |
2306 | 0 | || dwg->num_classes > 100 + (size / sizeof (Dwg_Class))) |
2307 | 0 | { |
2308 | 0 | LOG_ERROR ("Invalid max class number %d", (int)max_num); |
2309 | 0 | dwg->num_classes = 0; |
2310 | 0 | if (sec_dat.chain) |
2311 | 0 | free (sec_dat.chain); |
2312 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
2313 | 0 | } |
2314 | 0 | assert (max_num >= 500); |
2315 | |
|
2316 | 0 | if (dat->from_version >= R_2007) |
2317 | 0 | { |
2318 | 0 | memset (&str_dat, 0, sizeof (str_dat)); |
2319 | 0 | section_string_stream (dwg, &sec_dat, bitsize, &str_dat); |
2320 | 0 | } |
2321 | |
|
2322 | 0 | dwg->dwg_class |
2323 | 0 | = (Dwg_Class *)calloc (dwg->num_classes, sizeof (Dwg_Class)); |
2324 | 0 | if (!dwg->dwg_class) |
2325 | 0 | { |
2326 | 0 | LOG_ERROR ("Out of memory"); |
2327 | 0 | if (sec_dat.chain) |
2328 | 0 | free (sec_dat.chain); |
2329 | 0 | return DWG_ERR_OUTOFMEM; |
2330 | 0 | } |
2331 | | |
2332 | 0 | for (i = 0; i < dwg->num_classes; i++) |
2333 | 0 | { |
2334 | 0 | dwg->dwg_class[i].number = bit_read_BS (&sec_dat); |
2335 | 0 | dwg->dwg_class[i].proxyflag = bit_read_BS (&sec_dat); |
2336 | 0 | LOG_TRACE ("-------------------\n"); |
2337 | 0 | LOG_TRACE ("Number: %d [BS]\n", dwg->dwg_class[i].number); |
2338 | 0 | LOG_TRACE ("Proxyflag: %x [BS]\n", |
2339 | 0 | dwg->dwg_class[i].proxyflag); |
2340 | 0 | dwg_log_proxyflag (DWG_LOGLEVEL, DWG_LOGLEVEL_TRACE, |
2341 | 0 | dwg->dwg_class[i].proxyflag); |
2342 | 0 | if (dwg->header.version >= R_2007) |
2343 | 0 | { |
2344 | 0 | unsigned int applen, dxflen; |
2345 | 0 | dwg->dwg_class[i].appname |
2346 | 0 | = (char *)bit_read_TU_len (&str_dat, &applen); |
2347 | 0 | dwg->dwg_class[i].cppname = (char *)bit_read_TU (&str_dat); |
2348 | 0 | dwg->dwg_class[i].dxfname_u |
2349 | 0 | = bit_read_TU_len (&str_dat, &dxflen); |
2350 | 0 | dwg->dwg_class[i].dxfname |
2351 | 0 | = bit_TU_to_utf8_len (dwg->dwg_class[i].dxfname_u, dxflen); |
2352 | 0 | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE) |
2353 | 0 | { |
2354 | 0 | char *appu8 = bit_TU_to_utf8_len ( |
2355 | 0 | (BITCODE_TU)dwg->dwg_class[i].appname, applen); |
2356 | 0 | LOG_TRACE ("Application name: \"%s\" [TU 0 (as utf-8)]\n", |
2357 | 0 | appu8); |
2358 | | // LOG_TRACE_TU ("Application name", |
2359 | | // dwg->dwg_class[i].appname, 0) |
2360 | 0 | LOG_TRACE_TU ("C++ class name ", dwg->dwg_class[i].cppname, |
2361 | 0 | 0); |
2362 | 0 | LOG_TRACE_TU ("DXF record name ", |
2363 | 0 | dwg->dwg_class[i].dxfname_u, 0); |
2364 | 0 | free (appu8); |
2365 | 0 | } |
2366 | 0 | } |
2367 | 0 | else |
2368 | 0 | { |
2369 | 0 | dwg->dwg_class[i].appname = bit_read_TV (&sec_dat); |
2370 | 0 | dwg->dwg_class[i].cppname = bit_read_TV (&sec_dat); |
2371 | 0 | dwg->dwg_class[i].dxfname = bit_read_TV (&sec_dat); |
2372 | 0 | LOG_TRACE ("Application name: %s [TV]\n", |
2373 | 0 | dwg->dwg_class[i].appname); |
2374 | 0 | LOG_TRACE ("C++ class name: %s [TV]\n", |
2375 | 0 | dwg->dwg_class[i].cppname); |
2376 | 0 | LOG_TRACE ("DXF record name: %s [TV]\n", |
2377 | 0 | dwg->dwg_class[i].dxfname); |
2378 | 0 | } |
2379 | 0 | dwg->dwg_class[i].is_zombie |
2380 | 0 | = bit_read_B (&sec_dat); // now called proxy |
2381 | 0 | dwg->dwg_class[i].item_class_id = bit_read_BS (&sec_dat); |
2382 | 0 | LOG_TRACE ("Class ID: 0x%x [BS] " |
2383 | 0 | "(0x1f3 for object, 0x1f2 for entity)\n", |
2384 | 0 | dwg->dwg_class[i].item_class_id); |
2385 | |
|
2386 | 0 | dwg->dwg_class[i].num_instances = bit_read_BL (&sec_dat); |
2387 | 0 | dwg->dwg_class[i].dwg_version = bit_read_BS (&sec_dat); |
2388 | 0 | dwg->dwg_class[i].maint_version = bit_read_BS (&sec_dat); |
2389 | 0 | dwg->dwg_class[i].unknown_1 = bit_read_BL (&sec_dat); |
2390 | 0 | dwg->dwg_class[i].unknown_1 = bit_read_BL (&sec_dat); |
2391 | 0 | LOG_TRACE ("num_instances: %u\n", |
2392 | 0 | dwg->dwg_class[i].num_instances); |
2393 | 0 | LOG_HANDLE ("dwg version: %u (%u)\n", |
2394 | 0 | dwg->dwg_class[i].dwg_version, |
2395 | 0 | dwg->dwg_class[i].maint_version); |
2396 | 0 | LOG_HANDLE ("unknown: %u %u\n", dwg->dwg_class[i].unknown_1, |
2397 | 0 | dwg->dwg_class[i].unknown_2); |
2398 | |
|
2399 | 0 | if (dwg->dwg_class[i].dxfname |
2400 | 0 | && strEQ (dwg->dwg_class[i].dxfname, "LAYOUT")) |
2401 | 0 | dwg->layout_type = dwg->dwg_class[i].number; |
2402 | 0 | } |
2403 | 0 | } |
2404 | 0 | else |
2405 | 0 | { |
2406 | 0 | LOG_ERROR ("Failed to find class section sentinel"); |
2407 | 0 | free (sec_dat.chain); |
2408 | 0 | return DWG_ERR_CLASSESNOTFOUND; |
2409 | 0 | } |
2410 | | |
2411 | | // then RS: CRC |
2412 | | // dwg_sentinel(DWG_SENTINEL_CLASS_END) |
2413 | | // SINCE(R_2004) 8 unknown bytes |
2414 | | |
2415 | 0 | free (sec_dat.chain); |
2416 | 0 | return 0; |
2417 | 0 | } |
2418 | | |
2419 | | /* R2004, 2010+ Header Section |
2420 | | */ |
2421 | | static int |
2422 | | read_2004_section_header (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2423 | 0 | { |
2424 | 0 | int error; |
2425 | 0 | Bit_Chain sec_dat = { 0 }; |
2426 | |
|
2427 | 0 | sec_dat.opts = dwg->opts & DWG_OPTS_LOGLEVEL; |
2428 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_HEADER); |
2429 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
2430 | 0 | { |
2431 | 0 | LOG_ERROR ("Failed to read compressed %s section", "Header"); |
2432 | 0 | if (sec_dat.chain) |
2433 | 0 | free (sec_dat.chain); |
2434 | 0 | return error; |
2435 | 0 | } |
2436 | | #ifdef DEBUG |
2437 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
2438 | | { |
2439 | | FILE *fp = fopen ("decomp_hea.bin", "wb"); |
2440 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
2441 | | fclose (fp); |
2442 | | } |
2443 | | #endif |
2444 | 0 | if (dat->size - dat->byte <= 200) |
2445 | 0 | { |
2446 | 0 | LOG_ERROR ("Not enough space for HEADER %" PRIuSIZE, |
2447 | 0 | dat->size - dat->byte); |
2448 | 0 | return error | DWG_ERR_INVALIDDWG; |
2449 | 0 | } |
2450 | | |
2451 | 0 | if (bit_search_sentinel (&sec_dat, |
2452 | 0 | dwg_sentinel (DWG_SENTINEL_VARIABLE_BEGIN))) |
2453 | 0 | { |
2454 | 0 | LOG_TRACE ("\nHeader\n-------------------\n"); |
2455 | 0 | dwg->header_vars.size = bit_read_RL (&sec_dat); |
2456 | 0 | LOG_TRACE ("size: " FORMAT_RL " [RL]\n", dwg->header_vars.size); |
2457 | 0 | PRE (R_2007a) |
2458 | 0 | { |
2459 | 0 | error |
2460 | 0 | |= dwg_decode_header_variables (&sec_dat, &sec_dat, &sec_dat, dwg); |
2461 | 0 | } |
2462 | 0 | else |
2463 | 0 | { |
2464 | 0 | Bit_Chain hdl_dat, str_dat; |
2465 | 0 | BITCODE_RL endbits = 160; // start bit: 16 sentinel + 4 size |
2466 | 0 | hdl_dat = sec_dat; |
2467 | 0 | str_dat = sec_dat; |
2468 | 0 | if (dwg->header.maint_version > 3 || dat->from_version >= R_2018) |
2469 | 0 | { |
2470 | 0 | dwg->header_vars.bitsize_hi = bit_read_RL (&sec_dat); |
2471 | 0 | LOG_TRACE ("bitsize_hi: " FORMAT_RL " [RL]\n", |
2472 | 0 | dwg->header_vars.bitsize_hi); |
2473 | 0 | endbits += 32; // 192 |
2474 | 0 | } |
2475 | 0 | dwg->header_vars.bitsize = bit_read_RL (&sec_dat); |
2476 | 0 | LOG_TRACE ("bitsize: " FORMAT_RL " [RL]\n", dwg->header_vars.bitsize); |
2477 | 0 | endbits += dwg->header_vars.bitsize; |
2478 | 0 | bit_set_position (&hdl_dat, endbits); |
2479 | 0 | section_string_stream (dwg, &sec_dat, dwg->header_vars.bitsize, |
2480 | 0 | &str_dat); |
2481 | 0 | error |
2482 | 0 | |= dwg_decode_header_variables (&sec_dat, &hdl_dat, &str_dat, dwg); |
2483 | 0 | } |
2484 | 0 | } |
2485 | 0 | free (sec_dat.chain); |
2486 | 0 | return error; |
2487 | 0 | } |
2488 | | |
2489 | | /* R2004, 2010+ Handles Section |
2490 | | */ |
2491 | | static int |
2492 | | read_2004_section_handles (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2493 | 0 | { |
2494 | 0 | Bit_Chain obj_dat = { 0 }, hdl_dat = { 0 }; |
2495 | 0 | BITCODE_RS section_size = 0; |
2496 | 0 | size_t endpos; |
2497 | 0 | int error; |
2498 | |
|
2499 | 0 | obj_dat.opts = hdl_dat.opts = dwg->opts & DWG_OPTS_LOGLEVEL; |
2500 | 0 | error = read_2004_compressed_section (dat, dwg, &obj_dat, SECTION_OBJECTS); |
2501 | 0 | if (error >= DWG_ERR_CRITICAL || !obj_dat.chain) |
2502 | 0 | { |
2503 | 0 | LOG_ERROR ("Failed to read compressed %s section", "AcDbObjects"); |
2504 | 0 | if (obj_dat.chain) |
2505 | 0 | free (obj_dat.chain); |
2506 | 0 | return error; |
2507 | 0 | } |
2508 | | #ifdef DEBUG |
2509 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
2510 | | { |
2511 | | FILE *fp = fopen ("decomp_obj.bin", "wb"); |
2512 | | fwrite (obj_dat.chain, 1, obj_dat.size, fp); |
2513 | | fclose (fp); |
2514 | | } |
2515 | | #endif |
2516 | | |
2517 | 0 | error = read_2004_compressed_section (dat, dwg, &hdl_dat, SECTION_HANDLES); |
2518 | 0 | if (error >= DWG_ERR_CRITICAL || !hdl_dat.chain) |
2519 | 0 | { |
2520 | 0 | LOG_ERROR ("Failed to read compressed %s section", "Handles"); |
2521 | 0 | free (obj_dat.chain); |
2522 | 0 | if (hdl_dat.chain) |
2523 | 0 | free (hdl_dat.chain); |
2524 | 0 | return error; |
2525 | 0 | } |
2526 | | #ifdef DEBUG |
2527 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
2528 | | { |
2529 | | FILE *fp = fopen ("decomp_hdl.bin", "wb"); |
2530 | | fwrite (hdl_dat.chain, 1, hdl_dat.size, fp); |
2531 | | fclose (fp); |
2532 | | } |
2533 | | #endif |
2534 | | |
2535 | 0 | endpos = hdl_dat.byte + hdl_dat.size; |
2536 | 0 | dwg->num_objects = 0; |
2537 | |
|
2538 | 0 | do |
2539 | 0 | { |
2540 | 0 | size_t last_offset; |
2541 | | // BITCODE_RLL last_handle; |
2542 | 0 | size_t oldpos = 0; |
2543 | 0 | size_t startpos = hdl_dat.byte; |
2544 | 0 | size_t max_handles = hdl_dat.size * 2; |
2545 | 0 | uint16_t crc1, crc2; |
2546 | |
|
2547 | 0 | section_size = bit_read_RS_BE (&hdl_dat); |
2548 | 0 | LOG_TRACE ("\nHandles page size: %u [RS_BE]\n", section_size); |
2549 | | /* *********************************************** |
2550 | | * ODA p. 251 "Note that each section is cut off at a maximum length of |
2551 | | * 2032." BUT in fact files exist with 2036 section size */ |
2552 | 0 | if (section_size > 2040) |
2553 | 0 | { |
2554 | 0 | LOG_ERROR ("Object-map/handles page size greater than 2040!"); |
2555 | 0 | if (hdl_dat.chain) |
2556 | 0 | free (hdl_dat.chain); |
2557 | 0 | if (obj_dat.chain) |
2558 | 0 | free (obj_dat.chain); |
2559 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
2560 | 0 | } |
2561 | | |
2562 | 0 | last_offset = 0; |
2563 | 0 | while ((long)(hdl_dat.byte - startpos) < (long)section_size) |
2564 | 0 | { |
2565 | 0 | int added; |
2566 | 0 | BITCODE_UMC handleoff; |
2567 | 0 | BITCODE_MC offset; |
2568 | 0 | BITCODE_RLL last_handle |
2569 | 0 | = dwg->num_objects |
2570 | 0 | ? dwg->object[dwg->num_objects - 1].handle.value |
2571 | 0 | : 0; |
2572 | 0 | BITCODE_MC prevsize |
2573 | 0 | = dwg->num_objects ? dwg->object[dwg->num_objects - 1].size + 4 |
2574 | 0 | : 0; |
2575 | |
|
2576 | 0 | oldpos = hdl_dat.byte; |
2577 | | // the offset from the previous handle. default: 1, unsigned |
2578 | 0 | handleoff = bit_read_UMC (&hdl_dat); |
2579 | | // the offset from the previous address. default: obj->size |
2580 | 0 | offset = bit_read_MC (&hdl_dat); |
2581 | 0 | if (!handleoff || handleoff > max_handles - last_handle |
2582 | 0 | || (offset > -4 && offset < prevsize)) |
2583 | 0 | { |
2584 | 0 | LOG_WARN ("Ignore invalid handleoff (@%" PRIuSIZE ")", oldpos); |
2585 | 0 | if (offset == 1 |
2586 | 0 | || (offset > 0 && offset < prevsize && prevsize > 0) |
2587 | 0 | || (offset < 0 && labs ((long)offset) < prevsize |
2588 | 0 | && prevsize > 0)) |
2589 | 0 | { |
2590 | 0 | if (offset != prevsize) |
2591 | 0 | LOG_WARN ("offset " FORMAT_MC |
2592 | 0 | " looks wrong, should be prevsize " FORMAT_MC |
2593 | 0 | " + 4", |
2594 | 0 | offset, prevsize - 4); |
2595 | | // handleoff = 1; |
2596 | | // offset = prevsize; |
2597 | | // LOG_WARN ("Recover invalid handleoff to %" PRIuSIZE " and |
2598 | | // offset to %ld", |
2599 | | // handleoff, offset); |
2600 | 0 | } |
2601 | 0 | } |
2602 | 0 | last_offset += offset; |
2603 | 0 | LOG_TRACE ("\n< Next object: %lu ", (unsigned long)dwg->num_objects); |
2604 | 0 | LOG_HANDLE ("Handleoff: " FORMAT_UMC " [UMC] " |
2605 | 0 | "Offset: " FORMAT_MC " [MC] @%" PRIuSIZE "\n", |
2606 | 0 | handleoff, offset, last_offset); |
2607 | |
|
2608 | 0 | if (hdl_dat.byte == oldpos) // ?? completely unrelated |
2609 | 0 | break; |
2610 | | |
2611 | 0 | added = dwg_decode_add_object (dwg, &obj_dat, &obj_dat, last_offset); |
2612 | 0 | if (added > 0) |
2613 | 0 | error |= added; |
2614 | | // else re-allocated |
2615 | | // we don't stop encoding on single errors, but we sum them all up |
2616 | | // as combined bitmask |
2617 | 0 | } |
2618 | |
|
2619 | 0 | if (hdl_dat.byte == oldpos) |
2620 | 0 | break; |
2621 | | #if 0 |
2622 | | if (!bit_check_CRC(&hdl_dat, startpos, 0xC0C1)) |
2623 | | error |= DWG_ERR_WRONGCRC; |
2624 | | //LOG_WARN("Handles section CRC mismatch at offset %zx", startpos); |
2625 | | #else |
2626 | 0 | crc1 = bit_calc_CRC (0xC0C1, &(hdl_dat.chain[startpos]), |
2627 | 0 | hdl_dat.byte - startpos); |
2628 | 0 | crc2 = bit_read_RS_BE (&hdl_dat); |
2629 | 0 | LOG_TRACE ("Handles page crc: %04X [RS_BE]\n", crc2); |
2630 | 0 | if (crc1 == crc2) |
2631 | 0 | { |
2632 | 0 | LOG_INSANE ("Handles page CRC: %04X from %" PRIuSIZE "-%" PRIuSIZE |
2633 | 0 | "=%ld\n", |
2634 | 0 | crc2, startpos, hdl_dat.byte - 2, |
2635 | 0 | (long)(hdl_dat.byte - startpos - 2)); |
2636 | 0 | } |
2637 | 0 | else |
2638 | 0 | { |
2639 | 0 | LOG_WARN ("Handles page CRC mismatch: %04X vs calc. %04X from " |
2640 | 0 | "%" PRIuSIZE "-%" PRIuSIZE "=%ld\n", |
2641 | 0 | crc2, crc1, startpos, hdl_dat.byte - 2, |
2642 | 0 | (long)(hdl_dat.byte - startpos - 2)); |
2643 | 0 | error |= DWG_ERR_WRONGCRC; |
2644 | 0 | } |
2645 | 0 | #endif |
2646 | |
|
2647 | 0 | if (hdl_dat.byte >= endpos) |
2648 | 0 | break; |
2649 | 0 | } |
2650 | 0 | while (section_size > 2); |
2651 | | |
2652 | 0 | free (hdl_dat.chain); |
2653 | 0 | free (obj_dat.chain); |
2654 | 0 | return error; |
2655 | 0 | } |
2656 | | |
2657 | | // may return OUTOFBOUNDS, needs to free the chain then |
2658 | | static int |
2659 | | summaryinfo_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2660 | 0 | { |
2661 | 0 | Bit_Chain *str_dat = dat; |
2662 | 0 | Dwg_SummaryInfo *_obj = &dwg->summaryinfo; |
2663 | 0 | Dwg_Object *obj = NULL; |
2664 | 0 | int error = 0; |
2665 | | |
2666 | | // clang-format off |
2667 | 0 | #include "summaryinfo.spec" |
2668 | | // clang-format on |
2669 | |
|
2670 | 0 | return error; |
2671 | 0 | } |
2672 | | |
2673 | | /* R2004, 2010+ SummaryInfo Section |
2674 | | */ |
2675 | | static int |
2676 | | read_2004_section_summary (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2677 | 0 | { |
2678 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
2679 | | // not compressed, page size: 0x100 |
2680 | 0 | int error = read_2004_compressed_section (dat, dwg, &sec_dat, |
2681 | 0 | SECTION_SUMMARYINFO); // always 9 |
2682 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
2683 | 0 | { |
2684 | 0 | LOG_ERROR ("Failed to read uncompressed %s section", "SummaryInfo"); |
2685 | 0 | if (sec_dat.chain) |
2686 | 0 | free (sec_dat.chain); |
2687 | 0 | return error; |
2688 | 0 | } |
2689 | | #ifdef DEBUG |
2690 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
2691 | | { |
2692 | | FILE *fp = fopen ("decomp_si.bin", "wb"); |
2693 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
2694 | | fclose (fp); |
2695 | | } |
2696 | | #endif |
2697 | | |
2698 | 0 | if (dwg->header.summaryinfo_address != (BITCODE_RL)dat->byte) |
2699 | 0 | LOG_WARN ("summaryinfo_address mismatch: " FORMAT_RL " != %" PRIuSIZE, |
2700 | 0 | dwg->header.summaryinfo_address, dat->byte); |
2701 | 0 | LOG_TRACE ("SummaryInfo (%" PRIuSIZE ")\n-------------------\n", |
2702 | 0 | sec_dat.size); |
2703 | 0 | old_dat = *dat; |
2704 | 0 | dat = &sec_dat; // restrict in size |
2705 | 0 | bit_chain_set_version (&old_dat, dat); |
2706 | |
|
2707 | 0 | error = summaryinfo_private (dat, dwg); |
2708 | |
|
2709 | 0 | if (sec_dat.chain) |
2710 | 0 | free (sec_dat.chain); |
2711 | 0 | *dat = old_dat; // unrestrict |
2712 | 0 | return error; |
2713 | 0 | } |
2714 | | |
2715 | | // may return OUTOFBOUNDS, needs to free the chain then |
2716 | | static int |
2717 | | auxheader_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2718 | 0 | { |
2719 | 0 | Bit_Chain *str_dat = dat; |
2720 | 0 | Dwg_AuxHeader *_obj = &dwg->auxheader; |
2721 | 0 | Dwg_Object *obj = NULL; |
2722 | 0 | int error = 0; |
2723 | 0 | BITCODE_BL vcount; |
2724 | 0 | if (!dat->chain || !dat->size) |
2725 | 0 | return 1; |
2726 | | |
2727 | | // clang-format off |
2728 | 0 | #include "auxheader.spec" |
2729 | | // clang-format on |
2730 | | |
2731 | 0 | return error; |
2732 | 0 | } |
2733 | | |
2734 | | // r13 - r2000 |
2735 | | static int |
2736 | | secondheader_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2737 | 0 | { |
2738 | 0 | Bit_Chain *str_dat = dat; |
2739 | 0 | Dwg_SecondHeader *_obj = &dwg->secondheader; |
2740 | | // for error logging only: |
2741 | 0 | #ifndef __cplusplus |
2742 | 0 | Dwg_Object *obj = &(Dwg_Object){ .name = (char *)"2NDHEADER" }; |
2743 | | #else |
2744 | | Dwg_Object xobj; |
2745 | | xobj.name = (char *)"2NDHEADER"; |
2746 | | Dwg_Object *obj = &xobj; |
2747 | | #endif |
2748 | 0 | int error = 0; |
2749 | 0 | BITCODE_BL vcount; |
2750 | 0 | if (!dat->chain || !dat->size) |
2751 | 0 | return 1; |
2752 | | |
2753 | | // clang-format off |
2754 | 0 | #include "2ndheader.spec" |
2755 | | |
2756 | | // Compute handle values from raw big-endian bytes (reverse of bit_H_to_dat) |
2757 | 0 | for (unsigned i = 0; i < _obj->num_handles; i++) |
2758 | 0 | { |
2759 | 0 | Dwg_SecondHeader_Handles *h = &_obj->handles[i]; |
2760 | 0 | if (h->num_hdl <= 8) |
2761 | 0 | { |
2762 | 0 | h->value = 0; |
2763 | 0 | for (int k = 0; k < h->num_hdl; k++) |
2764 | 0 | h->value = (h->value << 8) | h->hdl[k]; |
2765 | 0 | } |
2766 | 0 | LOG_TRACE ("[%u] %s: 0.%hu." FORMAT_HV "\n", (unsigned)i, |
2767 | 0 | h->name ? h->name : "", h->num_hdl, h->value); |
2768 | 0 | } |
2769 | | // clang-format on |
2770 | |
|
2771 | 0 | if (!bit_check_CRC (dat, _obj->address + 16, 0xC0C1)) |
2772 | 0 | error |= DWG_ERR_WRONGCRC; |
2773 | |
|
2774 | 0 | DEBUG_HERE |
2775 | 0 | VERSIONS (R_14, R_2000) |
2776 | 0 | { |
2777 | 0 | FIELD_RLL (junk_r14, 0); |
2778 | 0 | } |
2779 | |
|
2780 | 0 | return error; |
2781 | 0 | } |
2782 | | |
2783 | | static int |
2784 | | objfreespace_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2785 | 0 | { |
2786 | | // Bit_Chain *str_dat = dat; |
2787 | 0 | Dwg_ObjFreeSpace *_obj = &dwg->objfreespace; |
2788 | 0 | Dwg_Object *obj = NULL; |
2789 | 0 | int error = 0; |
2790 | | // BITCODE_BL vcount; |
2791 | 0 | if (!dat->chain || !dat->size) |
2792 | 0 | return 1; |
2793 | | |
2794 | | // clang-format off |
2795 | 0 | #include "objfreespace.spec" |
2796 | | // clang-format on |
2797 | |
|
2798 | 0 | return error; |
2799 | 0 | } |
2800 | | |
2801 | | /* R13c3+ AuxHeader Section |
2802 | | */ |
2803 | | static int |
2804 | | read_2004_section_auxheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2805 | 0 | { |
2806 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
2807 | 0 | int error; |
2808 | | // type: 2, compressed, page size: 0x7400 |
2809 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_AUXHEADER); |
2810 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
2811 | 0 | { |
2812 | 0 | LOG_ERROR ("Failed to read uncompressed %s section", "AuxHeader"); |
2813 | 0 | if (sec_dat.chain) |
2814 | 0 | free (sec_dat.chain); |
2815 | 0 | return error; |
2816 | 0 | } |
2817 | | #ifdef DEBUG |
2818 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
2819 | | { |
2820 | | FILE *fp = fopen ("decomp_auxh.bin", "wb"); |
2821 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
2822 | | fclose (fp); |
2823 | | } |
2824 | | #endif |
2825 | | |
2826 | 0 | LOG_TRACE ("AuxHeader (%" PRIuSIZE ")\n-------------------\n", sec_dat.size); |
2827 | 0 | old_dat = *dat; |
2828 | 0 | dat = &sec_dat; // restrict in size |
2829 | 0 | bit_chain_set_version (&old_dat, dat); |
2830 | |
|
2831 | 0 | error = auxheader_private (dat, dwg); |
2832 | |
|
2833 | 0 | LOG_TRACE ("\n"); |
2834 | 0 | if (sec_dat.chain) |
2835 | 0 | free (sec_dat.chain); |
2836 | 0 | *dat = old_dat; // unrestrict |
2837 | 0 | return error; |
2838 | 0 | } |
2839 | | |
2840 | | // may return OUTOFBOUNDS, needs to free the chain then |
2841 | | // page size: 0x80, max seen max_decomp_size: 0x380 |
2842 | | static int |
2843 | | appinfo_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2844 | 0 | { |
2845 | 0 | Bit_Chain *str_dat = dat; |
2846 | 0 | Dwg_AppInfo *_obj = &dwg->appinfo; |
2847 | 0 | Dwg_Object *obj = NULL; |
2848 | 0 | int error = 0; |
2849 | 0 | if (!dat->chain || !dat->size) |
2850 | 0 | return 1; |
2851 | | |
2852 | | // clang-format off |
2853 | 0 | #include "appinfo.spec" |
2854 | | // clang-format on |
2855 | | |
2856 | 0 | if (_obj->version) |
2857 | 0 | { |
2858 | 0 | if (_obj->class_version > 2 |
2859 | 0 | && bit_wcs2len ((BITCODE_TU)_obj->version) >= 6) |
2860 | 0 | { |
2861 | 0 | is_teigha = memcmp (_obj->version, "T\0e\0i\0g\0h\0a\0", 12) == 0; |
2862 | 0 | LOG_TRACE ("is_teigha: %s\n", is_teigha ? "true" : "false"); |
2863 | 0 | } |
2864 | 0 | else if (_obj->class_version == 2 && dwg->header.version < R_2007 |
2865 | 0 | && strlen (_obj->version) >= 6) |
2866 | 0 | { |
2867 | 0 | is_teigha = memcmp (_obj->version, "Teigha", 6) == 0; |
2868 | 0 | LOG_TRACE ("is_teigha: %s\n", is_teigha ? "true" : "false"); |
2869 | 0 | } |
2870 | 0 | } |
2871 | 0 | return error; |
2872 | 0 | } |
2873 | | |
2874 | | /* R2004, 2010+ AppInfo Section |
2875 | | */ |
2876 | | static int |
2877 | | read_2004_section_appinfo (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2878 | 0 | { |
2879 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
2880 | 0 | int error; |
2881 | 0 | Dwg_AppInfo *_obj = &dwg->appinfo; |
2882 | | // type: 0xc or 0xb |
2883 | | // not compressed, page size: 0x80 |
2884 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_APPINFO); |
2885 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
2886 | 0 | { |
2887 | 0 | LOG_INFO ("%s section not found\n", "AppInfo"); |
2888 | 0 | if (sec_dat.chain) |
2889 | 0 | free (sec_dat.chain); |
2890 | 0 | return 0; |
2891 | 0 | } |
2892 | | #ifdef DEBUG |
2893 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
2894 | | { |
2895 | | FILE *fp = fopen ("decomp_ai.bin", "wb"); |
2896 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
2897 | | fclose (fp); |
2898 | | } |
2899 | | #endif |
2900 | | |
2901 | 0 | LOG_TRACE ("AppInfo (%" PRIuSIZE ")\n-------------------\n", sec_dat.size); |
2902 | 0 | _obj->size = sec_dat.size & 0xFFFFFFFF; |
2903 | 0 | FREE_IF (_obj->unknown_bits); |
2904 | 0 | _obj->unknown_bits = bit_read_TF (&sec_dat, _obj->size); |
2905 | 0 | bit_set_position (&sec_dat, 0); |
2906 | 0 | old_dat = *dat; |
2907 | 0 | dat = &sec_dat; // restrict in size |
2908 | 0 | bit_chain_set_version (&old_dat, dat); |
2909 | |
|
2910 | 0 | error = appinfo_private (dat, dwg); |
2911 | |
|
2912 | 0 | LOG_TRACE ("\n"); |
2913 | 0 | if (sec_dat.chain) |
2914 | 0 | free (sec_dat.chain); |
2915 | 0 | *dat = old_dat; // unrestrict |
2916 | 0 | return error; |
2917 | 0 | } |
2918 | | |
2919 | | // may return OUTOFBOUNDS |
2920 | | static int |
2921 | | filedeplist_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2922 | 0 | { |
2923 | 0 | Dwg_FileDepList *_obj = &dwg->filedeplist; |
2924 | 0 | Dwg_Object *obj = NULL; // for obj->size overflow check |
2925 | 0 | int error = 0; |
2926 | 0 | BITCODE_BL vcount; |
2927 | | |
2928 | | // clang-format off |
2929 | 0 | #include "filedeplist.spec" |
2930 | | // clang-format on |
2931 | |
|
2932 | 0 | return error; |
2933 | 0 | } |
2934 | | |
2935 | | /* r18 FileDepList Section |
2936 | | */ |
2937 | | static int |
2938 | | read_2004_section_filedeplist (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2939 | 0 | { |
2940 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
2941 | 0 | int error; |
2942 | | // not compressed, page size: 0x80. 0xc or 0xd |
2943 | 0 | error |
2944 | 0 | = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_FILEDEPLIST); |
2945 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
2946 | 0 | { |
2947 | 0 | LOG_INFO ("%s section not found\n", "FileDepList"); |
2948 | 0 | if (sec_dat.chain) |
2949 | 0 | free (sec_dat.chain); |
2950 | 0 | return 0; |
2951 | 0 | } |
2952 | | #ifdef DEBUG |
2953 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
2954 | | { |
2955 | | FILE *fp = fopen ("decomp_fd.bin", "wb"); |
2956 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
2957 | | fclose (fp); |
2958 | | } |
2959 | | #endif |
2960 | | |
2961 | 0 | LOG_TRACE ("FileDepList (%" PRIuSIZE ")\n-------------------\n", |
2962 | 0 | sec_dat.size); |
2963 | 0 | old_dat = *dat; |
2964 | 0 | dat = &sec_dat; // restrict in size |
2965 | 0 | bit_chain_set_version (&old_dat, dat); |
2966 | |
|
2967 | 0 | error = filedeplist_private (dat, dwg); |
2968 | |
|
2969 | 0 | LOG_TRACE ("\n"); |
2970 | 0 | if (sec_dat.chain) |
2971 | 0 | free (sec_dat.chain); |
2972 | 0 | *dat = old_dat; // unrestrict |
2973 | 0 | return error; |
2974 | 0 | } |
2975 | | |
2976 | | // may return OUTOFBOUNDS |
2977 | | static int |
2978 | | security_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2979 | 0 | { |
2980 | 0 | Bit_Chain *str_dat = dat; |
2981 | 0 | Dwg_Security *_obj = &dwg->security; |
2982 | 0 | Dwg_Object *obj = NULL; |
2983 | 0 | int error = 0; |
2984 | 0 | memset (_obj, 0, sizeof (Dwg_Security)); |
2985 | | |
2986 | | // clang-format off |
2987 | 0 | #include "security.spec" |
2988 | | // clang-format on |
2989 | |
|
2990 | 0 | return error; |
2991 | 0 | } |
2992 | | |
2993 | | /* r18 Security Section, if saved with password |
2994 | | */ |
2995 | | static int |
2996 | | read_2004_section_security (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
2997 | 0 | { |
2998 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
2999 | 0 | int error; |
3000 | | // compressed, page size: 0x7400 |
3001 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_SECURITY); |
3002 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
3003 | 0 | { |
3004 | 0 | LOG_INFO ("%s section not found\n", "Security"); |
3005 | 0 | if (sec_dat.chain) |
3006 | 0 | free (sec_dat.chain); |
3007 | 0 | return 0; |
3008 | 0 | } |
3009 | | #ifdef DEBUG |
3010 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
3011 | | { |
3012 | | FILE *fp = fopen ("decomp_sec.bin", "wb"); |
3013 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
3014 | | fclose (fp); |
3015 | | } |
3016 | | #endif |
3017 | | |
3018 | 0 | LOG_TRACE ("Security (%" PRIuSIZE ")\n-------------------\n", sec_dat.size); |
3019 | 0 | old_dat = *dat; |
3020 | 0 | dat = &sec_dat; // restrict in size |
3021 | 0 | bit_chain_set_version (&old_dat, dat); |
3022 | |
|
3023 | 0 | error = security_private (dat, dwg); |
3024 | |
|
3025 | 0 | LOG_TRACE ("\n"); |
3026 | 0 | if (sec_dat.chain) |
3027 | 0 | free (sec_dat.chain); |
3028 | 0 | *dat = old_dat; // unrestrict |
3029 | 0 | return error; |
3030 | 0 | } |
3031 | | |
3032 | | #if 0 |
3033 | | static int |
3034 | | signature_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3035 | | { |
3036 | | Bit_Chain *str_dat = dat; |
3037 | | struct Dwg_Signature *_obj = &dwg->signature; |
3038 | | Dwg_Object *obj = NULL; |
3039 | | int error = 0; |
3040 | | // clang-format off |
3041 | | #include "signature.spec" |
3042 | | // clang-format on |
3043 | | return error; |
3044 | | } |
3045 | | |
3046 | | /* Signature Section, not written nor documented by Teigha |
3047 | | */ |
3048 | | static int |
3049 | | read_2004_section_signature (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3050 | | { |
3051 | | Bit_Chain old_dat, sec_dat = { 0 }; |
3052 | | int error; |
3053 | | const char *secname = "Signature"; |
3054 | | |
3055 | | error = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_SIGNATURE); |
3056 | | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
3057 | | { |
3058 | | LOG_INFO ("%s section not found\n", secname); |
3059 | | if (sec_dat.chain) |
3060 | | free (sec_dat.chain); |
3061 | | return 0; |
3062 | | } |
3063 | | # ifdef DEBUG |
3064 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) { |
3065 | | FILE *fp = fopen ("decomp_sig.bin", "wb"); |
3066 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
3067 | | fclose(fp); |
3068 | | } |
3069 | | # endif |
3070 | | |
3071 | | LOG_TRACE ("Signature (%" PRIuSIZE ")\n-------------------\n", sec_dat.size); |
3072 | | old_dat = *dat; |
3073 | | dat = &sec_dat; // restrict in size |
3074 | | bit_chain_set_version (&old_dat, dat); |
3075 | | |
3076 | | error |= signature_private (dat, dwg); |
3077 | | |
3078 | | LOG_TRACE ("\n"); |
3079 | | if (sec_dat.chain) |
3080 | | free (sec_dat.chain); |
3081 | | *dat = old_dat; // unrestrict |
3082 | | return error; |
3083 | | } |
3084 | | #endif |
3085 | | |
3086 | | /* VBAProject Section. TODO dwg_decode_ole2 |
3087 | | */ |
3088 | | static int |
3089 | | read_2004_section_vbaproject (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3090 | 0 | { |
3091 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
3092 | 0 | int error; |
3093 | 0 | Dwg_VBAProject *_obj = &dwg->vbaproject; |
3094 | 0 | if (!dwg->header.vbaproj_address) |
3095 | 0 | { |
3096 | 0 | LOG_INFO ("No %s section. Empty header.vbaproj_address\n", "VBAProject"); |
3097 | 0 | return 0; |
3098 | 0 | } |
3099 | | // compressed |
3100 | 0 | error |
3101 | 0 | = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_VBAPROJECT); |
3102 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
3103 | 0 | { |
3104 | 0 | LOG_INFO ("%s section not found\n", "VBAProject"); |
3105 | 0 | if (sec_dat.chain) |
3106 | 0 | free (sec_dat.chain); |
3107 | 0 | return 0; |
3108 | 0 | } |
3109 | | #ifdef DEBUG |
3110 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
3111 | | { |
3112 | | FILE *fp = fopen ("decomp_vba.bin", "wb"); |
3113 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
3114 | | fclose (fp); |
3115 | | } |
3116 | | #endif |
3117 | | |
3118 | 0 | LOG_TRACE ("VBAProject (%" PRIuSIZE ")\n-------------------\n", |
3119 | 0 | sec_dat.size); |
3120 | 0 | old_dat = *dat; |
3121 | 0 | dat = &sec_dat; // restrict in size |
3122 | 0 | bit_chain_set_version (&old_dat, dat); |
3123 | | |
3124 | | // DEBUG_HERE dwg_decode_ole2 () (MS-CFB starts at offset 0x10) |
3125 | | // https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/575462ba-bf67-4190-9fac-c275523c75fc |
3126 | 0 | _obj->size = dat->size & 0xFFFFFFFF; |
3127 | 0 | _obj->unknown_bits = bit_read_TF (dat, _obj->size); |
3128 | 0 | LOG_TRACE_TF (_obj->unknown_bits, _obj->size); |
3129 | |
|
3130 | 0 | LOG_TRACE ("\n"); |
3131 | 0 | if (sec_dat.chain) |
3132 | 0 | free (sec_dat.chain); |
3133 | 0 | *dat = old_dat; // unrestrict |
3134 | 0 | return error; |
3135 | 0 | } |
3136 | | |
3137 | | /* AppInfoHistory Section |
3138 | | */ |
3139 | | static int |
3140 | | read_2004_section_appinfohistory (Bit_Chain *restrict dat, |
3141 | | Dwg_Data *restrict dwg) |
3142 | 0 | { |
3143 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
3144 | 0 | int error; |
3145 | 0 | Dwg_AppInfoHistory *_obj = &dwg->appinfohistory; |
3146 | | // compressed |
3147 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, |
3148 | 0 | SECTION_APPINFOHISTORY); |
3149 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
3150 | 0 | { |
3151 | 0 | LOG_INFO ("%s section not found\n", "AppInfoHistory"); |
3152 | 0 | if (sec_dat.chain) |
3153 | 0 | free (sec_dat.chain); |
3154 | 0 | return 0; |
3155 | 0 | } |
3156 | | #ifdef DEBUG |
3157 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
3158 | | { |
3159 | | FILE *fp = fopen ("decomp_aih.bin", "wb"); |
3160 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
3161 | | fclose (fp); |
3162 | | } |
3163 | | #endif |
3164 | | |
3165 | 0 | LOG_TRACE ("AppInfoHistory (%" PRIuSIZE ")\n-------------------\n", |
3166 | 0 | sec_dat.size); |
3167 | 0 | old_dat = *dat; |
3168 | 0 | dat = &sec_dat; // restrict in size |
3169 | 0 | bit_chain_set_version (&old_dat, dat); |
3170 | | |
3171 | | // DEBUG_HERE |
3172 | 0 | _obj->size = dat->size & 0xFFFFFFFF; |
3173 | 0 | _obj->unknown_bits = bit_read_TF (dat, _obj->size); |
3174 | 0 | LOG_TRACE_TF (_obj->unknown_bits, _obj->size); |
3175 | |
|
3176 | 0 | LOG_TRACE ("\n"); |
3177 | 0 | if (sec_dat.chain) |
3178 | 0 | free (sec_dat.chain); |
3179 | 0 | *dat = old_dat; // unrestrict |
3180 | 0 | return error; |
3181 | 0 | } |
3182 | | |
3183 | | // may return OUTOFBOUNDS |
3184 | | static int |
3185 | | revhistory_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3186 | 0 | { |
3187 | 0 | Bit_Chain *str_dat = dat; |
3188 | 0 | Dwg_RevHistory *_obj = &dwg->revhistory; |
3189 | 0 | Dwg_Object *obj = NULL; |
3190 | 0 | int error = 0; |
3191 | | |
3192 | | // clang-format off |
3193 | 0 | #include "revhistory.spec" |
3194 | | // clang-format on |
3195 | |
|
3196 | 0 | return error; |
3197 | 0 | } |
3198 | | |
3199 | | /* RevHistory Section |
3200 | | */ |
3201 | | static int |
3202 | | read_2004_section_revhistory (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3203 | 0 | { |
3204 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
3205 | 0 | int error; |
3206 | | // compressed |
3207 | 0 | error |
3208 | 0 | = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_REVHISTORY); |
3209 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
3210 | 0 | { |
3211 | 0 | LOG_INFO ("%s section not found\n", "RevHistory"); |
3212 | 0 | if (sec_dat.chain) |
3213 | 0 | free (sec_dat.chain); |
3214 | 0 | return 0; |
3215 | 0 | } |
3216 | | #ifdef DEBUG |
3217 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
3218 | | { |
3219 | | FILE *fp = fopen ("decomp_rh.bin", "wb"); |
3220 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
3221 | | fclose (fp); |
3222 | | } |
3223 | | #endif |
3224 | | |
3225 | 0 | LOG_TRACE ("RevHistory (%" PRIuSIZE ")\n-------------------\n", |
3226 | 0 | sec_dat.size); |
3227 | 0 | old_dat = *dat; |
3228 | 0 | dat = &sec_dat; // restrict in size |
3229 | 0 | bit_chain_set_version (&old_dat, dat); |
3230 | |
|
3231 | 0 | error = revhistory_private (dat, dwg); |
3232 | |
|
3233 | 0 | LOG_TRACE ("\n"); |
3234 | 0 | if (sec_dat.chain) |
3235 | 0 | free (sec_dat.chain); |
3236 | 0 | *dat = old_dat; // unrestrict |
3237 | 0 | return error; |
3238 | 0 | } |
3239 | | |
3240 | | /* ObjFreeSpace Section |
3241 | | */ |
3242 | | static int |
3243 | | read_2004_section_objfreespace (Bit_Chain *restrict dat, |
3244 | | Dwg_Data *restrict dwg) |
3245 | 0 | { |
3246 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
3247 | 0 | int error; |
3248 | 0 | Dwg_ObjFreeSpace *_obj = &dwg->objfreespace; |
3249 | | |
3250 | | // compressed |
3251 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, |
3252 | 0 | SECTION_OBJFREESPACE); |
3253 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
3254 | 0 | { |
3255 | 0 | LOG_INFO ("%s section not found\n", "ObjFreeSpace"); |
3256 | 0 | if (sec_dat.chain) |
3257 | 0 | free (sec_dat.chain); |
3258 | 0 | return 0; |
3259 | 0 | } |
3260 | | #ifdef DEBUG |
3261 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
3262 | | { |
3263 | | FILE *fp = fopen ("decomp_ofs.bin", "wb"); |
3264 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
3265 | | fclose (fp); |
3266 | | } |
3267 | | #endif |
3268 | | |
3269 | 0 | LOG_TRACE ("ObjFreeSpace (%" PRIuSIZE ")\n-------------------\n", |
3270 | 0 | sec_dat.size); |
3271 | 0 | old_dat = *dat; |
3272 | 0 | dat = &sec_dat; // restrict in size |
3273 | 0 | bit_chain_set_version (&old_dat, dat); |
3274 | | |
3275 | | // clang-format off |
3276 | 0 | #include "objfreespace.spec" |
3277 | | // clang-format on |
3278 | |
|
3279 | 0 | LOG_TRACE ("\n"); |
3280 | 0 | if (sec_dat.chain) |
3281 | 0 | free (sec_dat.chain); |
3282 | 0 | *dat = old_dat; // unrestrict |
3283 | 0 | return error; |
3284 | 0 | } |
3285 | | |
3286 | | /* Template Section. Optional r2004, mandatory r2007+ (but violated by Teigha) |
3287 | | Contains the MEASUREMENT variable (0 = English, 1 = Metric). |
3288 | | */ |
3289 | | static int |
3290 | | read_2004_section_template (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3291 | 0 | { |
3292 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
3293 | 0 | int error; |
3294 | | // compressed |
3295 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_TEMPLATE); |
3296 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
3297 | 0 | { |
3298 | 0 | UNTIL (R_2004) |
3299 | 0 | { |
3300 | 0 | LOG_INFO ("%s section not found\n", "Template"); |
3301 | 0 | } |
3302 | 0 | LATER_VERSIONS |
3303 | 0 | { |
3304 | | // violated by Teigha 4.3.2 |
3305 | 0 | LOG_ERROR ("%s section not found\n", "Template"); |
3306 | 0 | } |
3307 | 0 | if (sec_dat.chain) |
3308 | 0 | free (sec_dat.chain); |
3309 | 0 | return 0; |
3310 | 0 | } |
3311 | | #ifdef DEBUG |
3312 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
3313 | | { |
3314 | | FILE *fp = fopen ("decomp_temp.bin", "wb"); |
3315 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
3316 | | fclose (fp); |
3317 | | } |
3318 | | #endif |
3319 | | |
3320 | 0 | LOG_TRACE ("Template (%" PRIuSIZE ")\n-------------------\n", sec_dat.size); |
3321 | 0 | old_dat = *dat; |
3322 | 0 | dat = &sec_dat; // restrict in size |
3323 | 0 | bit_chain_set_version (&old_dat, dat); |
3324 | |
|
3325 | 0 | error |= template_private (dat, dwg); |
3326 | |
|
3327 | 0 | LOG_TRACE ("\n"); |
3328 | 0 | if (sec_dat.chain) |
3329 | 0 | free (sec_dat.chain); |
3330 | 0 | *dat = old_dat; // unrestrict |
3331 | 0 | return error; |
3332 | 0 | } |
3333 | | |
3334 | | static int |
3335 | | acds_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3336 | 0 | { |
3337 | 0 | Bit_Chain *str_dat = dat; |
3338 | 0 | Dwg_AcDs *_obj = &dwg->acds; |
3339 | 0 | Dwg_Object *obj = NULL; |
3340 | 0 | BITCODE_BL rcount3 = 0, rcount4, vcount; |
3341 | 0 | int error = 0; |
3342 | | |
3343 | | // clang-format off |
3344 | 0 | #include "acds.spec" |
3345 | | // clang-format on |
3346 | | |
3347 | 0 | return error; |
3348 | 0 | } |
3349 | | |
3350 | | /* datastorage section. Optional, since r2013 |
3351 | | Contains the SAB binary ACIS data, version 2 |
3352 | | */ |
3353 | | static int |
3354 | | read_2004_section_acds (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3355 | 0 | { |
3356 | 0 | Bit_Chain old_dat, sec_dat = { 0 }; |
3357 | 0 | int error; |
3358 | 0 | const char *secname = "AcDsPrototype_1b"; |
3359 | | |
3360 | | // compressed, pagesize 0x7400, type 13 |
3361 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_ACDS); |
3362 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
3363 | 0 | { |
3364 | 0 | LOG_INFO ("%s section not found\n", secname); |
3365 | 0 | if (sec_dat.chain) |
3366 | 0 | free (sec_dat.chain); |
3367 | 0 | return 0; |
3368 | 0 | } |
3369 | | #ifdef DEBUG |
3370 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
3371 | | { |
3372 | | FILE *fp = fopen ("decomp_acds.bin", "wb"); |
3373 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
3374 | | fclose (fp); |
3375 | | } |
3376 | | #endif |
3377 | | |
3378 | 0 | LOG_TRACE ("AcDs datastorage (%" PRIuSIZE ")\n-------------------\n", |
3379 | 0 | sec_dat.size); |
3380 | 0 | old_dat = *dat; |
3381 | 0 | dat = &sec_dat; // restrict in size |
3382 | 0 | bit_chain_set_version (&old_dat, dat); |
3383 | |
|
3384 | 0 | error |= acds_private (dat, dwg); |
3385 | 0 | error &= ~DWG_ERR_SECTIONNOTFOUND; |
3386 | |
|
3387 | 0 | LOG_TRACE ("\n"); |
3388 | 0 | if (sec_dat.chain) |
3389 | 0 | free (sec_dat.chain); |
3390 | 0 | *dat = old_dat; // unrestrict |
3391 | 0 | return error; |
3392 | 0 | } |
3393 | | |
3394 | | static int // thumbnail |
3395 | | read_2004_section_preview (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3396 | 0 | { |
3397 | 0 | Bit_Chain sec_dat = { 0 }; |
3398 | 0 | int error = 0; |
3399 | 0 | BITCODE_RL size; |
3400 | 0 | BITCODE_RC type; |
3401 | 0 | unsigned char *sentinel; |
3402 | | |
3403 | | // not compressed, num_sections: 1 |
3404 | 0 | error = read_2004_compressed_section (dat, dwg, &sec_dat, SECTION_PREVIEW); |
3405 | 0 | if (error >= DWG_ERR_CRITICAL || !sec_dat.chain) |
3406 | 0 | { |
3407 | 0 | LOG_ERROR ("Failed to read uncompressed %s section", "Preview"); |
3408 | 0 | if (sec_dat.chain) |
3409 | 0 | free (sec_dat.chain); |
3410 | 0 | return error; |
3411 | 0 | } |
3412 | | #ifdef DEBUG |
3413 | | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
3414 | | { |
3415 | | FILE *fp = fopen ("decomp_pre.bin", "wb"); |
3416 | | fwrite (sec_dat.chain, 1, sec_dat.size, fp); |
3417 | | fclose (fp); |
3418 | | } |
3419 | | #endif |
3420 | | |
3421 | 0 | if (dwg->header.thumbnail_address != (BITCODE_RL)dat->byte) |
3422 | 0 | LOG_WARN ("thumbnail_address mismatch: " FORMAT_RL " != %" PRIuSIZE, |
3423 | 0 | dwg->header.thumbnail_address, dat->byte); |
3424 | 0 | LOG_TRACE ("Preview (%" PRIuSIZE ")\n-------------------\n", sec_dat.size); |
3425 | 0 | if (!sec_dat.chain || sec_dat.size < 32) |
3426 | 0 | { |
3427 | 0 | LOG_WARN ("Empty thumbnail"); |
3428 | 0 | if (sec_dat.chain) |
3429 | 0 | free (sec_dat.chain); |
3430 | 0 | return error; |
3431 | 0 | } |
3432 | 0 | sentinel = (unsigned char *)dwg_sentinel (DWG_SENTINEL_THUMBNAIL_BEGIN); |
3433 | 0 | if (memcmp (sentinel, sec_dat.chain, 16)) |
3434 | 0 | { |
3435 | 0 | LOG_WARN ("thumbnail sentinel mismatch"); |
3436 | 0 | free (sec_dat.chain); |
3437 | 0 | return error; |
3438 | 0 | } |
3439 | 0 | assert (sec_dat.size >= 32); |
3440 | 0 | assert (sec_dat.chain); |
3441 | 0 | dwg->thumbnail.size = sec_dat.size - 16; |
3442 | 0 | dwg->thumbnail.chain = sec_dat.chain; |
3443 | 0 | dwg->thumbnail.byte = 16; // sentinel |
3444 | |
|
3445 | 0 | dwg_bmp (dwg, &size, &type); |
3446 | | // various headers |
3447 | 0 | if (abs ((int)((long)size - (long)dwg->thumbnail.size)) > 200) |
3448 | 0 | LOG_WARN ("thumbnail.size mismatch: %" PRIuSIZE " != " FORMAT_RL, |
3449 | 0 | dwg->thumbnail.size, size); |
3450 | |
|
3451 | 0 | dat->byte += dwg->thumbnail.size; |
3452 | |
|
3453 | 0 | return error; |
3454 | 0 | } |
3455 | | |
3456 | | /* For decrypt and encrypt: symmetric, as it's just a simple XOR with a |
3457 | | one-time pad, generated here on the fly. */ |
3458 | | void |
3459 | | decrypt_R2004_header (BITCODE_RC *restrict dest, |
3460 | | const BITCODE_RC *restrict src, size_t size) |
3461 | 3.68k | { |
3462 | 3.68k | uint32_t rseed = 1; |
3463 | 519k | for (size_t i = 0; i < size; i++) |
3464 | 515k | { |
3465 | 515k | rseed *= 0x343fd; |
3466 | 515k | rseed += 0x269ec3; |
3467 | 515k | dest[i] = src[i] ^ (rseed >> 0x10); |
3468 | 515k | } |
3469 | 3.68k | } |
3470 | | |
3471 | | GCC30_DIAG_IGNORE (-Wformat-nonliteral) |
3472 | | static int |
3473 | | decode_R2004_header (Bit_Chain *restrict file_dat, Dwg_Data *restrict dwg) |
3474 | 0 | { |
3475 | 0 | int error = 0; |
3476 | 0 | Dwg_Object *obj = NULL; |
3477 | 0 | Dwg_R2004_Header *_obj = &dwg->fhdr.r2004_header; |
3478 | 0 | Bit_Chain *hdl_dat = file_dat; |
3479 | |
|
3480 | 0 | { |
3481 | 0 | const size_t size = sizeof (Dwg_R2004_Header); |
3482 | 0 | BITCODE_RC decrypted_data[sizeof (Dwg_R2004_Header)]; |
3483 | 0 | Bit_Chain decrypted_header_dat = *file_dat; |
3484 | 0 | Bit_Chain *dat; |
3485 | 0 | BITCODE_RL crc32, calc_crc32; |
3486 | |
|
3487 | 0 | decrypted_header_dat.size = size; |
3488 | 0 | decrypted_header_dat.chain = decrypted_data; |
3489 | 0 | decrypted_header_dat.byte = decrypted_header_dat.bit = 0; |
3490 | 0 | if (file_dat->size < size + (file_dat->byte + 80)) |
3491 | 0 | { |
3492 | 0 | LOG_ERROR ("Size underflow %" PRIuSIZE " for R2004_Header", |
3493 | 0 | file_dat->size); |
3494 | 0 | return DWG_ERR_INVALIDDWG; |
3495 | 0 | } |
3496 | | |
3497 | 0 | LOG_HANDLE ("encrypted R2004_Header (@%u.0-%" PRIuSIZE ".0, %" PRIuSIZE |
3498 | 0 | "):\n", |
3499 | 0 | 0x80, size + 0x80, size); |
3500 | 0 | LOG_TF_HEX (HANDLE, &file_dat->chain[0x80], (int)size); |
3501 | 0 | decrypt_R2004_header (decrypted_data, &file_dat->chain[0x80], size); |
3502 | 0 | LOG_HANDLE ("decrypted R2004_Header (@%u.0-%" PRIuSIZE ".0, %" PRIuSIZE |
3503 | 0 | "):\n", |
3504 | 0 | 0x80, size + 0x80, size); |
3505 | 0 | LOG_TF_HEX (HANDLE, &decrypted_data[0], size); |
3506 | |
|
3507 | 0 | dat = &decrypted_header_dat; |
3508 | 0 | dat->bit = 0; |
3509 | 0 | dat->byte = 0UL; |
3510 | 0 | LOG_TRACE ("\n#### r2004 File Header ####\n"); |
3511 | | // clang-format off |
3512 | 0 | #include "r2004_file_header.spec" |
3513 | | // clang-format on |
3514 | | |
3515 | 0 | if (memcmp (_obj->file_ID_string, "AcFssFcAJMB", 8)) |
3516 | 0 | { |
3517 | 0 | LOG_ERROR ("r2004_file_header decryption error"); |
3518 | 0 | return error | DWG_ERR_INVALIDDWG; |
3519 | 0 | } |
3520 | | // only really needed for r2004 encode later |
3521 | 0 | crc32 = _obj->crc32; |
3522 | 0 | _obj->crc32 = 0; |
3523 | | |
3524 | | // while calc crc the 4 CRC bytes should initialized to 0 zero |
3525 | 0 | decrypted_data[0x6c - 1] = 0; |
3526 | 0 | decrypted_data[0x6c - 2] = 0; |
3527 | 0 | decrypted_data[0x6c - 3] = 0; |
3528 | 0 | decrypted_data[0x6c - 4] = 0; |
3529 | | |
3530 | | // without the padding, but the crc32 as 0 |
3531 | 0 | calc_crc32 = bit_calc_CRC32 (0, &decrypted_data[0], 0x6c); |
3532 | 0 | _obj->crc32 = crc32; |
3533 | 0 | if (calc_crc32 != crc32) |
3534 | 0 | { |
3535 | 0 | LOG_INFO ("r2004_file_header CRC32 mismatch 0x%08x != 0x%08x\n", |
3536 | 0 | calc_crc32, crc32); |
3537 | 0 | } |
3538 | 0 | else |
3539 | 0 | { |
3540 | 0 | LOG_TRACE ("crc32 => 0x%08x (verified)\n", (unsigned)crc32); |
3541 | 0 | } |
3542 | 0 | } |
3543 | | |
3544 | | /*------------------------------------------------------------------------- |
3545 | | * Section Page Map |
3546 | | */ |
3547 | 0 | { |
3548 | 0 | BITCODE_RL checksum1, checksum2; |
3549 | 0 | Bit_Chain *dat = file_dat; |
3550 | 0 | size_t start; |
3551 | 0 | BITCODE_RC *map; |
3552 | 0 | LOG_INSANE ("@0x%zx\n", dat->byte); |
3553 | |
|
3554 | 0 | LOG_TRACE ("\n=== Read System Section (Section Page Map) @%lx ===\n\n", |
3555 | 0 | (unsigned long)dwg->fhdr.r2004_header.section_map_address |
3556 | 0 | + 0x100); |
3557 | 0 | dat->byte = dwg->fhdr.r2004_header.section_map_address + 0x100; |
3558 | 0 | start = dwg->fhdr.r2004_header.section_map_address; |
3559 | | |
3560 | | // Some section_map_address overflow past the dwg. GH #617 |
3561 | | // maybe search the magic type backwards then. (in 0x20 page boundary |
3562 | | // steps) e.g. 1344464555_1_2004 |
3563 | 0 | if (start > dat->size) |
3564 | 0 | { |
3565 | 0 | BITCODE_RL section_type; |
3566 | 0 | start = dat->size & 0xffffff00; |
3567 | 0 | LOG_INFO ("Searching for the Section Page Map backwards @%zx ...\n", |
3568 | 0 | start - 0x20); |
3569 | 0 | do |
3570 | 0 | { |
3571 | 0 | start -= 0x20; |
3572 | 0 | dat->byte = start; |
3573 | 0 | section_type = bit_read_RL (dat); |
3574 | 0 | LOG_INSANE ("section_type: " FORMAT_RLx " @%zx\n", section_type, |
3575 | 0 | dat->byte - 4); |
3576 | 0 | } |
3577 | 0 | while (section_type != 0x41630e3b && dat->byte > 0x120); |
3578 | 0 | if (section_type != 0x41630e3b) |
3579 | 0 | LOG_INFO ("Not found\n"); |
3580 | 0 | } |
3581 | | /* start may point near the end of the file (small or truncated |
3582 | | files), where reading the 0x100-byte page map header would run |
3583 | | past the end of the chain buffer. GHSA-c8cq-gr5h-7c6j */ |
3584 | 0 | if (start > dat->size || dat->size - start < 0x100) |
3585 | 0 | { |
3586 | 0 | LOG_ERROR ("Invalid Section Page Map address 0x%zx (file size " |
3587 | 0 | "0x%zx)\n", |
3588 | 0 | start, dat->size); |
3589 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
3590 | 0 | } |
3591 | 0 | map = &dat->chain[start]; |
3592 | 0 | LOG_INSANE ("section_map_address: 0x%zx + 0x100:\n", start); |
3593 | 0 | LOG_INSANE_TF (map, 0x100); |
3594 | 0 | LOG_INSANE ("@0x%zx\n", dat->byte); |
3595 | |
|
3596 | 0 | FIELD_RLx (section_type, 0); |
3597 | 0 | if (FIELD_VALUE (section_type) != 0x41630e3b) |
3598 | 0 | { |
3599 | 0 | dat->byte = start + 0x100 + 16; |
3600 | 0 | LOG_ERROR ("Invalid System Section Page Map type 0x%x != 0x41630e3b", |
3601 | 0 | FIELD_VALUE (section_type)); |
3602 | 0 | return DWG_ERR_SECTIONNOTFOUND; |
3603 | 0 | } |
3604 | 0 | FIELD_RL (decomp_data_size, 0); |
3605 | 0 | FIELD_RL (comp_data_size, 0); |
3606 | 0 | FIELD_RL (compression_type, 0); |
3607 | 0 | FIELD_RLx (checksum, 0); |
3608 | 0 | LOG_INSANE ("@0x%zx\n", dat->byte); |
3609 | | // get the seed from the header (skipping the checksum) |
3610 | 0 | dat->byte = start + 0x100; |
3611 | 0 | checksum1 = dwg_section_page_checksum (0, dat, 20, true); |
3612 | | // now the compressed buffer, not the header. not skipping the checksum |
3613 | 0 | dat->byte = start + 0x114; |
3614 | 0 | checksum2 = dwg_section_page_checksum (checksum1, dat, |
3615 | 0 | _obj->comp_data_size, false); |
3616 | 0 | LOG_TRACE ("checksum => 0x%08x with calculated seed 0x%08x\n", |
3617 | 0 | (unsigned)checksum2, (unsigned)checksum1); |
3618 | 0 | if (checksum2 == _obj->checksum) |
3619 | 0 | { |
3620 | 0 | LOG_TRACE ("checksum: 0x%08x (verified)\n", (unsigned)checksum2); |
3621 | 0 | } |
3622 | 0 | else |
3623 | 0 | { |
3624 | 0 | LOG_WARN ("checksum: 0x%08x (calculated) page checksum mismatch " |
3625 | 0 | "0x%zx-0x%zx\n", |
3626 | 0 | (unsigned)checksum2, start + 0x100, start + 0x114); |
3627 | 0 | error |= DWG_ERR_WRONGCRC; |
3628 | 0 | } |
3629 | 0 | } |
3630 | 0 | return error; |
3631 | 0 | } |
3632 | | |
3633 | | /* for 2004 and 2010+ */ |
3634 | | static int |
3635 | | decode_R2004 (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3636 | 0 | { |
3637 | 0 | int error = 0; |
3638 | 0 | Dwg_Section *section; |
3639 | |
|
3640 | 0 | { |
3641 | 0 | Dwg_Header *_obj = &dwg->header; |
3642 | 0 | Dwg_Object *obj = NULL; |
3643 | 0 | Bit_Chain *hdl_dat = dat; |
3644 | 0 | int i; |
3645 | 0 | BITCODE_BL vcount; |
3646 | 0 | assert (dat->byte == 0xb); // after version magic |
3647 | | |
3648 | | // clang-format off |
3649 | 0 | #include "header.spec" |
3650 | | // clang-format on |
3651 | 0 | } |
3652 | 0 | if ((dat->byte - 54) > 0x80) |
3653 | 0 | { |
3654 | 0 | LOG_HANDLE ("\nempty R2004 slack (@%" PRIuSIZE ".0-%u.0, %ld):\n", |
3655 | 0 | dat->byte - 54, 0x80, (long)(0x80 - (dat->byte - 54))); |
3656 | 0 | if (dat->byte > 54 && dat->chain) |
3657 | 0 | LOG_TF (HANDLE, &dat->chain[dat->byte], |
3658 | 0 | (int)(0x80 - (dat->byte - 54))); |
3659 | 0 | } |
3660 | |
|
3661 | 0 | error |= decode_R2004_header (dat, dwg); |
3662 | 0 | if (error > DWG_ERR_CRITICAL) |
3663 | 0 | return error; |
3664 | | |
3665 | 0 | error |= read_R2004_section_map (dat, dwg); |
3666 | 0 | if (!dwg->header.section || error >= DWG_ERR_CRITICAL) |
3667 | 0 | { |
3668 | 0 | LOG_ERROR ("Failed to read R2004 Section Page Map."); |
3669 | 0 | return error | DWG_ERR_INTERNALERROR; |
3670 | 0 | } |
3671 | | |
3672 | | /*------------------------------------------------------------------------- |
3673 | | * Section Info |
3674 | | */ |
3675 | 0 | section = find_section (dwg, dwg->fhdr.r2004_header.section_info_id); |
3676 | 0 | if (section) |
3677 | 0 | { |
3678 | 0 | Dwg_Object *obj = NULL; |
3679 | 0 | Dwg_Section *_obj = section; |
3680 | 0 | LOG_TRACE ("\n=== Data Section (Section Info %d) @%lx ===\n", |
3681 | 0 | dwg->fhdr.r2004_header.section_info_id, |
3682 | 0 | (unsigned long)section->address); |
3683 | 0 | dat->byte = section->address; |
3684 | |
|
3685 | 0 | FIELD_RLx (section_type, 0); |
3686 | 0 | if (FIELD_VALUE (section_type) != 0x4163003b) |
3687 | 0 | { |
3688 | 0 | LOG_ERROR ("Invalid Data Section Page Map type 0x%x != 0x4163003b", |
3689 | 0 | FIELD_VALUE (section_type)); |
3690 | 0 | return DWG_ERR_SECTIONNOTFOUND; |
3691 | 0 | } |
3692 | 0 | FIELD_RL (decomp_data_size, 0); |
3693 | 0 | FIELD_RL (comp_data_size, 0); |
3694 | 0 | FIELD_RL (compression_type, 0); |
3695 | 0 | FIELD_RLx (checksum, 0); |
3696 | | |
3697 | | // Data section map, par 4.5 |
3698 | 0 | error |= read_R2004_section_info (dat, dwg, _obj->comp_data_size, |
3699 | 0 | _obj->decomp_data_size); |
3700 | 0 | } |
3701 | 0 | else |
3702 | 0 | error |= DWG_ERR_SECTIONNOTFOUND; |
3703 | | |
3704 | 0 | error |= read_2004_section_header (dat, dwg); |
3705 | 0 | if (dwg->header.summaryinfo_address) |
3706 | 0 | error |= read_2004_section_summary (dat, dwg); |
3707 | 0 | error |= read_2004_section_classes (dat, dwg); |
3708 | 0 | error |= read_2004_section_handles (dat, dwg); |
3709 | 0 | error |= read_2004_section_auxheader (dat, dwg); |
3710 | 0 | if (dwg->header.thumbnail_address) |
3711 | 0 | error |= read_2004_section_preview (dat, dwg); |
3712 | 0 | error |= read_2004_section_appinfo (dat, dwg); |
3713 | 0 | error |= read_2004_section_appinfohistory (dat, dwg); |
3714 | 0 | error |= read_2004_section_filedeplist (dat, dwg); |
3715 | 0 | error |= read_2004_section_security (dat, dwg); |
3716 | 0 | error |= read_2004_section_revhistory (dat, dwg); |
3717 | 0 | error |= read_2004_section_objfreespace (dat, dwg); |
3718 | 0 | error |= read_2004_section_template (dat, dwg); |
3719 | 0 | if (dwg->header.vbaproj_address) |
3720 | 0 | error |= read_2004_section_vbaproject (dat, dwg); |
3721 | | // error |= read_2004_section_signature (dat, dwg); |
3722 | 0 | error |= read_2004_section_acds (dat, dwg); |
3723 | | |
3724 | | /* Clean up. XXX? Need this to write the sections, at least the name and |
3725 | | * type |
3726 | | */ |
3727 | | #if 0 |
3728 | | if (dwg->header.section_info != NULL) |
3729 | | { |
3730 | | unsigned u; |
3731 | | for (u = 0; u < dwg->header.num_infos; ++u) |
3732 | | if (dwg->header.section_info[u].sections != 0) |
3733 | | free(dwg->header.section_info[u].sections); |
3734 | | |
3735 | | free(dwg->header.section_info); |
3736 | | dwg->header.num_infos = 0; |
3737 | | } |
3738 | | #endif |
3739 | |
|
3740 | 0 | LOG_INFO ("\nnum_objects: %lu\n", (unsigned long)dwg->num_objects); |
3741 | 0 | LOG_TRACE ("num_object_refs: %lu\n", (unsigned long)dwg->num_object_refs); |
3742 | 0 | LOG_TRACE ("Resolving pointers from ObjectRef vector:\n"); |
3743 | 0 | error |= resolve_objectref_vector (dat, dwg); |
3744 | 0 | return error; |
3745 | 0 | } |
3746 | | |
3747 | | static int |
3748 | | decode_R2007 (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
3749 | 40 | { |
3750 | 40 | Bit_Chain hdl_dat = { 0 }; |
3751 | 40 | int error; |
3752 | | |
3753 | 40 | hdl_dat = *dat; |
3754 | 40 | { |
3755 | 40 | Dwg_Header *_obj = &dwg->header; |
3756 | 40 | Dwg_Object *obj = NULL; |
3757 | 40 | int i; |
3758 | 40 | BITCODE_BL vcount; |
3759 | 40 | assert (dat->byte == 0xb); // after version magic |
3760 | | |
3761 | | // clang-format off |
3762 | 40 | #include "header.spec" |
3763 | | // clang-format on |
3764 | 40 | } |
3765 | | |
3766 | | // this includes classes, header, handles + objects |
3767 | 40 | error = read_r2007_meta_data (dat, &hdl_dat, dwg); |
3768 | | |
3769 | 40 | LOG_INFO ("\nnum_objects: %lu\n", (unsigned long)dwg->num_objects); |
3770 | 40 | LOG_TRACE ("num_object_refs: %lu\n", (unsigned long)dwg->num_object_refs); |
3771 | 40 | if (error >= DWG_ERR_CRITICAL) |
3772 | 10 | { |
3773 | 10 | LOG_ERROR ("Failed to read 2007 meta data"); |
3774 | 10 | return error; |
3775 | 10 | } |
3776 | | |
3777 | 30 | LOG_TRACE ("Resolving pointers from ObjectRef vector:\n"); |
3778 | 30 | return error | resolve_objectref_vector (dat, dwg); |
3779 | 40 | } |
3780 | | |
3781 | | /*-------------------------------------------------------------------------------- |
3782 | | * Private functions |
3783 | | * |
3784 | | * EED "Extended Entity Data": |
3785 | | * There's an array of obj->num_eed obj->eed[] entries. |
3786 | | * Each eed member has size, handle, the raw[size] buffer and the decoded data. |
3787 | | * Each obj->eed[].data member is further separated into DXF+1000 codes, for |
3788 | | * strings, numbers, points, ... |
3789 | | * Those subgroups have an empty raw, size, and the prev. handle. |
3790 | | */ |
3791 | | |
3792 | | #undef LOG_POS |
3793 | 23.2M | #define LOG_POS LOG_RPOS |
3794 | | |
3795 | | static int |
3796 | | eed_need_size (unsigned long need, BITCODE_BS have) |
3797 | 554k | { |
3798 | | // 1 more for the initial eed.data.code byte |
3799 | 554k | if ((need + 1) > (unsigned long)have) |
3800 | 13.5k | { |
3801 | 13.5k | LOG_ERROR ("Invalid EED size %lu > %u", need, (unsigned)have); |
3802 | 13.5k | return 1; |
3803 | 13.5k | } |
3804 | 540k | return 0; |
3805 | 554k | } |
3806 | | |
3807 | | static int |
3808 | | dwg_decode_eed_data (Bit_Chain *restrict dat, Dwg_Eed_Data *restrict data, |
3809 | | size_t end, BITCODE_BS size) |
3810 | 437k | { |
3811 | 437k | int lenc; |
3812 | 437k | BITCODE_BS j; |
3813 | 437k | size_t lens; |
3814 | | |
3815 | 437k | data->code = bit_read_RC (dat); |
3816 | 437k | LOG_TRACE ("code: %d [RC], ", (int)data->code); |
3817 | 437k | switch (data->code) |
3818 | 437k | { |
3819 | 147k | case 0: |
3820 | 147k | PRE (R_13b1) |
3821 | 1.66k | { |
3822 | 1.66k | if (eed_need_size (1, size)) |
3823 | 175 | return DWG_ERR_INVALIDEED; |
3824 | 1.49k | data->u.eed_0.is_tu = 0; |
3825 | 1.49k | data->u.eed_0.length = lenc = bit_read_RC (dat); |
3826 | 1.49k | if ((long)lenc > size - 3) |
3827 | 116 | { |
3828 | 116 | LOG_ERROR ("Invalid EED string len %d, max %d", lenc, |
3829 | 116 | (int)size - 3); |
3830 | 116 | dat->byte = end; |
3831 | 116 | break; |
3832 | 116 | } |
3833 | | /* code:1 + len:1 */ |
3834 | 1.37k | if (eed_need_size (lenc + 2, size)) |
3835 | 0 | return DWG_ERR_INVALIDEED; |
3836 | 1.37k | bit_read_fixed (dat, (BITCODE_RC *)data->u.eed_0.string, lenc); |
3837 | 1.37k | data->u.eed_0.string[lenc] = '\0'; |
3838 | 1.37k | LOG_TRACE ("string: len=%d [RC] \"%s\" [TF]", (int)lenc, |
3839 | 1.37k | data->u.eed_0.string); |
3840 | 1.37k | } |
3841 | 147k | VERSIONS (R_13b1, R_2007b) |
3842 | 145k | { |
3843 | 145k | if (eed_need_size (3, size)) |
3844 | 295 | return DWG_ERR_INVALIDEED; |
3845 | 145k | data->u.eed_0.is_tu = 0; |
3846 | 145k | data->u.eed_0.length = lenc = bit_read_RC (dat); |
3847 | 145k | data->u.eed_0.codepage = bit_read_RS_BE (dat); |
3848 | 145k | if ((long)lenc > size - 4) |
3849 | 11.5k | { |
3850 | 11.5k | LOG_ERROR ("Invalid EED string len %d, max %d", lenc, |
3851 | 11.5k | (int)size - 4); |
3852 | 11.5k | dat->byte = end; |
3853 | 11.5k | break; |
3854 | | #if 0 |
3855 | | obj->num_eed = 0; |
3856 | | if (obj->eed[idx].size) |
3857 | | free(obj->eed[idx].raw); |
3858 | | free(obj->eed[idx].data); |
3859 | | free(obj->eed); |
3860 | | obj->eed = NULL; |
3861 | | dat->byte = end; |
3862 | | return DWG_ERR_INVALIDEED; /* may not continue */ |
3863 | | #endif |
3864 | 11.5k | } |
3865 | | /* code:1 + len:1 + cp:2 */ |
3866 | 133k | if (eed_need_size (lenc + 3, size)) |
3867 | 0 | return DWG_ERR_INVALIDEED; |
3868 | 133k | bit_read_fixed (dat, (BITCODE_RC *)data->u.eed_0.string, lenc); |
3869 | 133k | data->u.eed_0.string[lenc] = '\0'; |
3870 | 133k | LOG_TRACE ("string: len=%d [RC] cp=%d [RS_BE] \"%s\" [TF]", (int)lenc, |
3871 | 133k | (int)data->u.eed_0.codepage, data->u.eed_0.string); |
3872 | 133k | } |
3873 | 135k | SINCE (R_2007a) |
3874 | 0 | { |
3875 | 0 | if (eed_need_size (2, size)) |
3876 | 0 | return DWG_ERR_INVALIDEED; |
3877 | 0 | data->u.eed_0.is_tu = 1; |
3878 | 0 | data->u.eed_0_r2007.length = bit_read_RS (dat); |
3879 | 0 | lens = data->u.eed_0_r2007.length; |
3880 | 0 | if (eed_need_size ((long)(lens * 2) + 2, size)) |
3881 | 0 | return DWG_ERR_INVALIDEED; |
3882 | | /* code:1 + len:2 NUL? */ |
3883 | 0 | for (j = 0; |
3884 | 0 | j < (BITCODE_BS)MIN (lens, (unsigned long)((size - 3) / 2)); j++) |
3885 | 0 | data->u.eed_0_r2007.string[j] = bit_read_RS (dat); |
3886 | | // data->u.eed_0_r2007.string[j] = 0; //already calloc'ed |
3887 | | #ifdef _WIN32 |
3888 | | LOG_TRACE ("wstring: len=%d [RS] \"" FORMAT_TU "\" [TU]", (int)lens, |
3889 | | data->u.eed_0_r2007.string); |
3890 | | #else |
3891 | 0 | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE) |
3892 | 0 | { |
3893 | 0 | char *u8 = bit_TU_to_utf8_len (data->u.eed_0_r2007.string, lens); |
3894 | 0 | LOG_TRACE ("wstring: len=%d [RS] \"%s\" [TU]", (int)lens, u8); |
3895 | 0 | free (u8); |
3896 | 0 | } |
3897 | 0 | #endif |
3898 | 0 | } |
3899 | 135k | break; |
3900 | 135k | case 1: |
3901 | 2.55k | if (eed_need_size (3, size)) |
3902 | 73 | return DWG_ERR_INVALIDEED; |
3903 | 2.47k | data->u.eed_1.appid_index = bit_read_RS (dat); |
3904 | 2.47k | LOG_TRACE ("appid_index: " FORMAT_RS " [RS]", data->u.eed_1.appid_index); |
3905 | 2.47k | break; |
3906 | 6.72k | case 2: |
3907 | 6.72k | if (eed_need_size (1, size)) |
3908 | 1 | return DWG_ERR_INVALIDEED; |
3909 | 6.72k | data->u.eed_2.close = bit_read_RC (dat); |
3910 | 6.72k | if (data->u.eed_2.close) |
3911 | 6.64k | { |
3912 | 6.64k | LOG_TRACE ("close: " FORMAT_RC " [RC]", data->u.eed_2.close); |
3913 | 6.64k | } |
3914 | 78 | else |
3915 | 78 | { |
3916 | 78 | LOG_TRACE ("open: " FORMAT_RC " [RC]", data->u.eed_2.close); |
3917 | 78 | } |
3918 | 6.72k | break; |
3919 | 3.75k | case 3: |
3920 | 3.75k | if (eed_need_size (8, size)) |
3921 | 100 | return DWG_ERR_INVALIDEED; |
3922 | 3.65k | PRE (R_13b1) |
3923 | 250 | { |
3924 | 250 | data->u.eed_3.layer = (BITCODE_RLL)bit_read_RS (dat); |
3925 | 250 | LOG_TRACE ("layer: " FORMAT_RLL " [RS]", data->u.eed_3.layer); |
3926 | 250 | } |
3927 | 3.40k | LATER_VERSIONS |
3928 | 3.40k | { |
3929 | 3.40k | data->u.eed_3.layer = bit_read_RLL (dat); |
3930 | 3.40k | LOG_TRACE ("layer: " FORMAT_RLL " [RLL]", data->u.eed_3.layer); |
3931 | 3.40k | } |
3932 | 3.65k | break; |
3933 | 109k | case 4: |
3934 | 109k | if (eed_need_size (1, size)) |
3935 | 9 | return DWG_ERR_INVALIDEED; |
3936 | 109k | data->u.eed_4.length = lenc = bit_read_RC (dat); |
3937 | 109k | if (eed_need_size (lenc + 1, size)) |
3938 | 6.63k | return DWG_ERR_INVALIDEED; |
3939 | | /* code:1 + len:1 */ |
3940 | 1.71M | for (j = 0; j < MIN (lenc, size - 2); j++) |
3941 | 1.61M | data->u.eed_4.data[j] = bit_read_RC (dat); |
3942 | 103k | LOG_TRACE ("binary[%d] \"%s\" [TF]", j - 1, data->u.eed_4.data); |
3943 | 103k | break; |
3944 | 18.6k | case 5: |
3945 | 18.6k | if (eed_need_size (8, size)) |
3946 | 5.81k | return DWG_ERR_INVALIDEED; |
3947 | 12.8k | data->u.eed_5.entity = bit_read_RLL_BE (dat); |
3948 | 12.8k | LOG_TRACE ("entity: " FORMAT_HV " [RLL_BE]", data->u.eed_5.entity); |
3949 | 12.8k | break; |
3950 | 1.29k | case 10: |
3951 | 2.26k | case 11: |
3952 | 2.80k | case 12: |
3953 | 4.75k | case 13: |
3954 | 5.56k | case 14: |
3955 | 16.9k | case 15: |
3956 | 16.9k | if (eed_need_size (3 * 8, size)) |
3957 | 403 | return DWG_ERR_INVALIDEED; |
3958 | 16.5k | data->u.eed_10.point.x = bit_read_RD (dat); |
3959 | 16.5k | data->u.eed_10.point.y = bit_read_RD (dat); |
3960 | 16.5k | data->u.eed_10.point.z = bit_read_RD (dat); |
3961 | 16.5k | LOG_TRACE ("3dpoint: (%f, %f, %f) [3RD]", data->u.eed_10.point.x, |
3962 | 16.5k | data->u.eed_10.point.y, data->u.eed_10.point.z); |
3963 | 16.5k | break; |
3964 | 1.06k | case 40: |
3965 | 2.28k | case 41: |
3966 | 2.37k | case 42: |
3967 | 2.37k | if (eed_need_size (8, size)) |
3968 | 4 | return DWG_ERR_INVALIDEED; |
3969 | 2.37k | data->u.eed_40.real = bit_read_RD (dat); |
3970 | 2.37k | LOG_TRACE ("real: %f [RD]", data->u.eed_40.real); |
3971 | 2.37k | break; |
3972 | 317 | case 70: |
3973 | 317 | if (eed_need_size (2, size)) |
3974 | 0 | return DWG_ERR_INVALIDEED; |
3975 | 317 | data->u.eed_70.rs = bit_read_RS (dat); |
3976 | 317 | LOG_TRACE ("short: " FORMAT_RS " [RS]", data->u.eed_70.rs); |
3977 | 317 | break; |
3978 | 524 | case 71: |
3979 | 524 | if (eed_need_size (4, size)) |
3980 | 64 | return DWG_ERR_INVALIDEED; |
3981 | 460 | data->u.eed_71.rl = bit_read_RL (dat); |
3982 | 460 | LOG_TRACE ("long: " FORMAT_RL " [RL]", data->u.eed_71.rl); |
3983 | 460 | if (data->u.eed_71.rl > 0x100000) |
3984 | 460 | LOG_TRACE (" " FORMAT_RLx " [RLx]", data->u.eed_71.rl); |
3985 | 460 | break; |
3986 | 128k | default: |
3987 | 128k | LOG_ERROR ("unknown EED code %d", data->code); |
3988 | 128k | LOG_POS |
3989 | 128k | dat->byte = end; |
3990 | 128k | LOG_POS |
3991 | 128k | return DWG_ERR_INVALIDEED; /* may continue */ |
3992 | 437k | } |
3993 | 437k | LOG_POS |
3994 | 295k | return 0; |
3995 | 437k | } |
3996 | | |
3997 | | /* for objects and entities */ |
3998 | | int |
3999 | | dwg_decode_eed (Bit_Chain *restrict dat, Dwg_Object_Object *restrict obj) |
4000 | 554k | { |
4001 | 554k | BITCODE_BS size = 0; |
4002 | 554k | int error = 0; |
4003 | 554k | unsigned int idx = 0; |
4004 | 554k | Dwg_Data *dwg = obj->dwg; |
4005 | 554k | Dwg_Object *_obj; |
4006 | 554k | size_t sav_byte = dat->byte; |
4007 | | |
4008 | 554k | if (!dwg) |
4009 | 0 | return DWG_ERR_INVALIDEED; |
4010 | 554k | _obj = &dwg->object[obj->objid]; /* Note that obj->objid may be 0 */ |
4011 | 554k | obj->num_eed = 0; |
4012 | 891k | while (1) |
4013 | 891k | { |
4014 | 891k | BITCODE_BS j; |
4015 | 891k | size_t end; |
4016 | | |
4017 | 891k | if (dat->from_version >= R_13b1) |
4018 | 754k | { |
4019 | 754k | size = bit_read_BS (dat); |
4020 | 754k | if (!size) |
4021 | 173k | break; |
4022 | 581k | LOG_TRACE ("EED[%u] size: " FORMAT_BS " [BS]", idx, size); |
4023 | 581k | } |
4024 | 137k | else |
4025 | 137k | { |
4026 | 137k | if (idx) |
4027 | 14.4k | break; |
4028 | 122k | size = (BITCODE_BS)bit_read_RS (dat); |
4029 | 122k | LOG_TRACE ("EED[%u] size: " FORMAT_BS " [RS]", idx, size); |
4030 | 122k | } |
4031 | | |
4032 | 891k | LOG_RPOS |
4033 | 704k | if (size > _obj->size || dat->byte == sav_byte) |
4034 | 367k | { |
4035 | 367k | LOG_ERROR ("Invalid EED size " FORMAT_BS " > %u", size, _obj->size); |
4036 | 367k | obj->num_eed = idx; |
4037 | 367k | return DWG_ERR_INVALIDEED; |
4038 | 367k | } |
4039 | | |
4040 | 336k | obj->num_eed = idx + 1; |
4041 | 336k | if (idx) /* just extend by one. not in chunks for now */ |
4042 | 135k | { |
4043 | 135k | obj->eed |
4044 | 135k | = (Dwg_Eed *)realloc (obj->eed, obj->num_eed * sizeof (Dwg_Eed)); |
4045 | 135k | memset (&obj->eed[idx], 0, sizeof (Dwg_Eed)); |
4046 | 135k | } |
4047 | 201k | else |
4048 | 201k | { |
4049 | 201k | obj->eed = (Dwg_Eed *)calloc (1, sizeof (Dwg_Eed)); |
4050 | 201k | } |
4051 | 336k | obj->eed[idx].size = size; |
4052 | 336k | if (dat->from_version >= R_13b1) |
4053 | 322k | { |
4054 | 322k | error |= bit_read_H (dat, &obj->eed[idx].handle); |
4055 | 322k | end = dat->byte + size; |
4056 | 322k | if (error) |
4057 | 178k | { |
4058 | 178k | LOG_ERROR ("No EED[%d].handle", idx); |
4059 | 178k | obj->eed[idx].size = 0; |
4060 | 178k | obj->num_eed--; |
4061 | 178k | if (!obj->num_eed) |
4062 | 43.6k | dwg_free_eed (_obj); |
4063 | 178k | dat->byte = end; // skip eed |
4064 | 178k | continue; // continue for size = bit_read_BS(dat) |
4065 | 178k | } |
4066 | 144k | else |
4067 | 144k | { |
4068 | 144k | LOG_TRACE ("EED[%u] handle: " FORMAT_H, idx, |
4069 | 144k | ARGS_H (obj->eed[idx].handle)); |
4070 | 144k | LOG_RPOS; |
4071 | 144k | if (dat->byte >= dat->size) |
4072 | 0 | end = dat->byte; |
4073 | 144k | if (_obj->fixedtype == DWG_TYPE_MLEADERSTYLE) |
4074 | 0 | { // check for is_new_format: has extended data for APPID |
4075 | | // “ACAD_MLEADERVER” |
4076 | 0 | Dwg_Object_Ref ref; |
4077 | 0 | ref.obj = NULL; |
4078 | 0 | ref.handleref = obj->eed[idx].handle; |
4079 | 0 | ref.absolute_ref = 0L; |
4080 | 0 | if (dwg_resolve_handleref (&ref, _obj)) |
4081 | 0 | { |
4082 | 0 | Dwg_Object *appid |
4083 | 0 | = dwg_get_first_object (dwg, DWG_TYPE_APPID_CONTROL); |
4084 | 0 | if (appid) |
4085 | 0 | { |
4086 | 0 | Dwg_Object_APPID_CONTROL *_appid |
4087 | 0 | = appid->tio.object->tio.APPID_CONTROL; |
4088 | | // search absref in APPID_CONTROL apps[] |
4089 | 0 | for (j = 0; j < _appid->num_entries; j++) |
4090 | 0 | { |
4091 | 0 | if (_appid->entries && _appid->entries[j] |
4092 | 0 | && _appid->entries[j]->absolute_ref |
4093 | 0 | == ref.absolute_ref) |
4094 | 0 | { |
4095 | 0 | Dwg_Object_MLEADERSTYLE *mstyle |
4096 | 0 | = obj->tio.MLEADERSTYLE; |
4097 | | // real value with code 70 follows |
4098 | 0 | mstyle->class_version = 2; |
4099 | 0 | LOG_TRACE ( |
4100 | 0 | "EED found ACAD_MLEADERVER " FORMAT_HV |
4101 | 0 | "\n", |
4102 | 0 | ref.absolute_ref); |
4103 | 0 | } |
4104 | 0 | } |
4105 | 0 | } |
4106 | 0 | } |
4107 | 0 | } |
4108 | 144k | } |
4109 | 322k | } |
4110 | 14.4k | else |
4111 | 14.4k | { |
4112 | 14.4k | end = dat->byte + size; |
4113 | 14.4k | } |
4114 | | |
4115 | 158k | sav_byte = dat->byte; |
4116 | 158k | obj->eed[idx].raw = bit_read_TF (dat, size); |
4117 | 158k | LOG_TRACE ("EED[%u] raw: %d\n", idx, size); |
4118 | 158k | LOG_INSANE_TF (obj->eed[idx].raw, size); |
4119 | | // LOG_TRACE ("\n"); |
4120 | 158k | dat->byte = sav_byte; |
4121 | | // LOG_RPOS |
4122 | | |
4123 | 582k | while (dat->byte < end) |
4124 | 437k | { |
4125 | 437k | obj->eed[idx].data = (Dwg_Eed_Data *)calloc (size + 8, 1); |
4126 | 437k | LOG_TRACE ("EED[%u] ", idx); |
4127 | 437k | error |= dwg_decode_eed_data (dat, obj->eed[idx].data, end, size); |
4128 | | // overflow or no advance |
4129 | 437k | if (dat->byte >= dat->size || dat->byte == sav_byte) |
4130 | 2.30k | error |= DWG_ERR_INVALIDEED; |
4131 | 437k | if (error & DWG_ERR_INVALIDEED) |
4132 | 142k | { |
4133 | 142k | free (obj->eed[idx].data); |
4134 | 142k | LOG_HANDLE (" invalid eed[%d]: skip", idx); |
4135 | 142k | LOG_RPOS |
4136 | 142k | obj->eed[idx].data = NULL; |
4137 | | // obj->num_eed--; // we still have .raw |
4138 | 142k | dat->byte = end; // skip eed |
4139 | 142k | continue; // continue for next size = bit_read_BS(dat) |
4140 | 142k | } |
4141 | | |
4142 | 295k | if (_obj->fixedtype == DWG_TYPE_MLEADERSTYLE |
4143 | 0 | && obj->tio.MLEADERSTYLE->class_version == 2 |
4144 | 0 | && obj->eed[idx].data->code == 70) |
4145 | 0 | { |
4146 | 0 | obj->tio.MLEADERSTYLE->class_version |
4147 | 0 | = obj->eed[idx].data->u.eed_70.rs; |
4148 | 0 | LOG_TRACE ("ACAD_MLEADERVER class_version: %d\n", |
4149 | 0 | obj->eed[idx].data->u.eed_70.rs); |
4150 | 0 | } |
4151 | 295k | if (dat->byte < end - 1) |
4152 | 281k | { |
4153 | 281k | idx++; |
4154 | 281k | obj->num_eed = idx + 1; |
4155 | 281k | size = (long)(end - dat->byte + 1); |
4156 | | // LOG_INSANE (" size remaining: %ld\n", (long)size); |
4157 | | // LOG_RPOS |
4158 | 281k | obj->eed = (Dwg_Eed *)realloc (obj->eed, |
4159 | 281k | obj->num_eed * sizeof (Dwg_Eed)); |
4160 | 281k | obj->eed[idx].handle = obj->eed[idx - 1].handle; |
4161 | 281k | obj->eed[idx].size = 0; |
4162 | 281k | obj->eed[idx].raw = NULL; |
4163 | 281k | sav_byte = dat->byte; |
4164 | 281k | } |
4165 | 13.8k | else |
4166 | 13.8k | { |
4167 | 13.8k | break; |
4168 | 13.8k | } |
4169 | 295k | } |
4170 | 158k | LOG_RPOS |
4171 | 158k | if (obj->eed[idx].raw) |
4172 | 73.5k | { |
4173 | 73.5k | dat->byte = end; |
4174 | 73.5k | LOG_RPOS |
4175 | 73.5k | } |
4176 | 158k | idx++; |
4177 | 158k | } |
4178 | 187k | LOG_HANDLE ("EED[%u] size: " FORMAT_BS " (end)", idx, size); |
4179 | 187k | LOG_RPOS |
4180 | 187k | LOG_TRACE ("num_eed: " FORMAT_BL "\n", obj->num_eed); |
4181 | 187k | return error; |
4182 | 554k | } |
4183 | | |
4184 | | /** OL2FRAME.data potentially contains as 128 byte of custom specific data: |
4185 | | BITCODE_BS oleversion; DXF 70, always 2 |
4186 | | BOTCODE_TF oleclient; DXF 3, e.g. OLE or Paintbrush Picture |
4187 | | BITCODE_3RD pt1; DXF 10, upper left corner |
4188 | | BITCODE_3RD pt2; DXF 11, lower right corner |
4189 | | |
4190 | | plus eventually: |
4191 | | T link_name; like C:\My Documents\excel.xls!Sheet1!R5C3:R8C3 |
4192 | | RC output_quality; |
4193 | | BD rotation |
4194 | | BD width; |
4195 | | BD height; |
4196 | | BD scale_width; |
4197 | | BD scale_height; |
4198 | | |
4199 | | The rest of data (&data[128]) contains the MS-CFB, see |
4200 | | https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cfb/53989ce4-7b05-4f8d-829b-d08d6148375b |
4201 | | e.g. decodable via py-oletools |
4202 | | */ |
4203 | | static int |
4204 | | dwg_decode_ole2 (Dwg_Entity_OLE2FRAME *restrict _obj) |
4205 | 1.16k | { |
4206 | 1.16k | Bit_Chain bdat; |
4207 | 1.16k | Bit_Chain *dat = &bdat; |
4208 | | |
4209 | 1.16k | dat->bit = 0; |
4210 | 1.16k | dat->byte = 0; |
4211 | 1.16k | dat->size = 0x80; |
4212 | 1.16k | dat->chain = (unsigned char *)&_obj->data[0]; |
4213 | 1.16k | dat->version = _obj->parent->dwg->header.version; |
4214 | 1.16k | dat->from_version = _obj->parent->dwg->header.from_version; |
4215 | | |
4216 | | // TODO decode the unknowns |
4217 | | /* Sample data from TS1.dwg: |
4218 | | 00000000: 8055 40f9 3284 d222 3e40 7436 e0d9 23fd .U@.2..">@t6..#. |
4219 | | 00000010: 32c0 0000 0000 0000 0000 d879 8900 cda2 2..........y.... |
4220 | | 00000020: 4140 7436 e0d9 23fd 32c0 0000 0000 0000 A@t6..#.2....... |
4221 | | 00000030: 0000 d879 8900 cda2 4140 1420 d4f3 b864 ...y....A@. ...d |
4222 | | 00000040: 36c0 0000 0000 0000 0000 40f9 3284 d222 6.........@.2.." |
4223 | | 00000050: 3e40 1420 d4f3 b864 36c0 0000 0000 0000 >@. ...d6....... |
4224 | | 00000060: 0000 021f 9114 0100 0000 0001 0000 0100 ................ |
4225 | | 00000070: 0000 0100 0000 0000 0100 0000 0090 0500 ................ |
4226 | | => from the DXF |
4227 | | oleversion 2 [70] |
4228 | | oleclient "OLE" [3] (but the cfb contains PBrush.9) |
4229 | | pt1 (30.13602472538446, -18.98882829402869, 0.0) [10] |
4230 | | pt2 (35.27188116753285, -22.39344715050545, 0.0) [11] |
4231 | | */ |
4232 | | // FIXME decode the fields |
4233 | | // FIELD_BS (oleversion, 70); |
4234 | | // FIELD_TV (oleclient, 3); |
4235 | | // FIELD_2BD (pt1, 10); |
4236 | | // FIELD_2BD (pt2, 11); |
4237 | 1.16k | _obj->oleversion = 2; |
4238 | 1.16k | _obj->oleclient = (BITCODE_TF) "OLE"; |
4239 | 1.16k | _obj->pt1.x = 30.13602472538446; |
4240 | 1.16k | _obj->pt1.y = -18.98882829402869; |
4241 | 1.16k | _obj->pt2.x = 35.27188116753285; |
4242 | 1.16k | _obj->pt2.y = -22.39344715050545; |
4243 | | |
4244 | | // next, see the MS-CFB format |
4245 | 1.16k | dat->bit = 0; |
4246 | 1.16k | dat->byte = 0; |
4247 | 1.16k | dat->size = _obj->data_size; |
4248 | 1.16k | dat->chain = (unsigned char *)&_obj->data[0x80]; |
4249 | | // TODO |
4250 | | |
4251 | 1.16k | return 0; |
4252 | 1.16k | } |
4253 | | |
4254 | | // for all obj->type < 500. if to check for the has_strings bit after bitsize |
4255 | | // TODO: generate this automatically |
4256 | | static int |
4257 | | obj_has_strings (unsigned int type) |
4258 | 0 | { |
4259 | 0 | switch (type) |
4260 | 0 | { |
4261 | 0 | case DWG_TYPE_TEXT: |
4262 | 0 | case DWG_TYPE_ATTRIB: |
4263 | 0 | case DWG_TYPE_ATTDEF: |
4264 | 0 | case DWG_TYPE_BLOCK: |
4265 | 0 | return 1; |
4266 | 0 | case DWG_TYPE_ENDBLK: |
4267 | 0 | case DWG_TYPE_SEQEND: |
4268 | 0 | case DWG_TYPE_INSERT: |
4269 | 0 | case DWG_TYPE_MINSERT: |
4270 | 0 | case DWG_TYPE_VERTEX_2D: |
4271 | 0 | case DWG_TYPE_VERTEX_3D: |
4272 | 0 | case DWG_TYPE_VERTEX_MESH: |
4273 | 0 | case DWG_TYPE_VERTEX_PFACE: |
4274 | 0 | case DWG_TYPE_VERTEX_PFACE_FACE: |
4275 | 0 | case DWG_TYPE_POLYLINE_2D: |
4276 | 0 | case DWG_TYPE_POLYLINE_3D: |
4277 | 0 | case DWG_TYPE_ARC: |
4278 | 0 | case DWG_TYPE_CIRCLE: |
4279 | 0 | case DWG_TYPE_LINE: |
4280 | 0 | return 0; |
4281 | 0 | case DWG_TYPE_DIMENSION_ORDINATE: |
4282 | 0 | case DWG_TYPE_DIMENSION_LINEAR: |
4283 | 0 | case DWG_TYPE_DIMENSION_ALIGNED: |
4284 | 0 | case DWG_TYPE_DIMENSION_ANG3PT: |
4285 | 0 | case DWG_TYPE_DIMENSION_ANG2LN: |
4286 | 0 | case DWG_TYPE_DIMENSION_RADIUS: |
4287 | 0 | case DWG_TYPE_DIMENSION_DIAMETER: |
4288 | 0 | return 1; |
4289 | 0 | case DWG_TYPE_POINT: |
4290 | 0 | case DWG_TYPE__3DFACE: |
4291 | 0 | case DWG_TYPE_POLYLINE_PFACE: |
4292 | 0 | case DWG_TYPE_POLYLINE_MESH: |
4293 | 0 | case DWG_TYPE_SOLID: |
4294 | 0 | case DWG_TYPE_TRACE: |
4295 | 0 | case DWG_TYPE_SHAPE: |
4296 | 0 | return 0; |
4297 | 0 | case DWG_TYPE_VIEWPORT: |
4298 | 0 | return 1; |
4299 | 0 | case DWG_TYPE_ELLIPSE: |
4300 | 0 | case DWG_TYPE_SPLINE: |
4301 | 0 | return 0; |
4302 | 0 | case DWG_TYPE_REGION: |
4303 | 0 | case DWG_TYPE__3DSOLID: |
4304 | 0 | case DWG_TYPE_BODY: |
4305 | 0 | return 1; |
4306 | 0 | case DWG_TYPE_RAY: |
4307 | 0 | case DWG_TYPE_XLINE: |
4308 | 0 | return 0; |
4309 | 0 | case DWG_TYPE_DICTIONARY: |
4310 | 0 | case DWG_TYPE_OLEFRAME: |
4311 | 0 | case DWG_TYPE_MTEXT: |
4312 | 0 | case DWG_TYPE_LEADER: |
4313 | 0 | case DWG_TYPE_TOLERANCE: |
4314 | 0 | return 1; |
4315 | 0 | case DWG_TYPE_MLINE: |
4316 | 0 | return 0; |
4317 | 0 | case DWG_TYPE_BLOCK_CONTROL: |
4318 | 0 | case DWG_TYPE_LAYER_CONTROL: |
4319 | 0 | case DWG_TYPE_STYLE_CONTROL: |
4320 | 0 | case DWG_TYPE_LTYPE_CONTROL: |
4321 | 0 | case DWG_TYPE_VIEW_CONTROL: |
4322 | 0 | case DWG_TYPE_UCS_CONTROL: |
4323 | 0 | case DWG_TYPE_VPORT_CONTROL: |
4324 | 0 | case DWG_TYPE_APPID_CONTROL: |
4325 | 0 | case DWG_TYPE_DIMSTYLE_CONTROL: |
4326 | 0 | case DWG_TYPE_VX_CONTROL: |
4327 | 0 | return 0; |
4328 | 0 | case DWG_TYPE_BLOCK_HEADER: |
4329 | 0 | case DWG_TYPE_LAYER: |
4330 | 0 | case DWG_TYPE_STYLE: |
4331 | 0 | case DWG_TYPE_LTYPE: |
4332 | 0 | case DWG_TYPE_VIEW: |
4333 | 0 | case DWG_TYPE_UCS: |
4334 | 0 | case DWG_TYPE_VPORT: |
4335 | 0 | case DWG_TYPE_APPID: |
4336 | 0 | case DWG_TYPE_DIMSTYLE: |
4337 | 0 | case DWG_TYPE_VX_TABLE_RECORD: |
4338 | 0 | return 1; |
4339 | 0 | case DWG_TYPE_GROUP: |
4340 | 0 | case DWG_TYPE_MLINESTYLE: |
4341 | 0 | case DWG_TYPE_OLE2FRAME: |
4342 | 0 | return 1; |
4343 | 0 | case DWG_TYPE_DUMMY: |
4344 | 0 | case DWG_TYPE_LONG_TRANSACTION: |
4345 | 0 | case DWG_TYPE_LWPOLYLINE: |
4346 | 0 | return 0; |
4347 | 0 | case DWG_TYPE_HATCH: |
4348 | 0 | case DWG_TYPE_XRECORD: |
4349 | 0 | return 1; |
4350 | 0 | case DWG_TYPE_PLACEHOLDER: |
4351 | 0 | return 0; |
4352 | 0 | case DWG_TYPE_VBA_PROJECT: |
4353 | 0 | case DWG_TYPE_LAYOUT: |
4354 | 0 | case DWG_TYPE_PROXY_ENTITY: |
4355 | 0 | case DWG_TYPE_PROXY_OBJECT: |
4356 | 0 | default: |
4357 | 0 | return 1; |
4358 | 0 | } |
4359 | 0 | } |
4360 | | |
4361 | | /* init and restrict the hdl_dat stream. */ |
4362 | | int |
4363 | | obj_handle_stream (Bit_Chain *restrict dat, Dwg_Object *restrict obj, |
4364 | | Bit_Chain *restrict hdl_dat) |
4365 | 703k | { |
4366 | 703k | size_t bit8 = obj->bitsize / 8; |
4367 | 703k | assert (dat != hdl_dat); |
4368 | | // The handle stream offset, i.e. end of the object, right after |
4369 | | // the has_strings bit. |
4370 | 703k | obj->hdlpos = obj->bitsize; // relative to dat |
4371 | | // restrict it to 0-end |
4372 | 703k | hdl_dat->byte = bit8; |
4373 | 703k | hdl_dat->bit = obj->bitsize % 8; |
4374 | | // bit_reset_chain (hdl_dat); //but keep the same start |
4375 | 703k | if (!obj->handlestream_size) // with strings we already did calc. it |
4376 | 703k | { |
4377 | 703k | obj->handlestream_size = (obj->size * 8) - obj->bitsize; |
4378 | 703k | LOG_TRACE (" Hdlsize: " FORMAT_UMC ",", obj->handlestream_size); |
4379 | 703k | } |
4380 | | // dat->size = bit8 + hdl_dat->bit ? 1 : 0; |
4381 | 703k | hdl_dat->size = obj->size; |
4382 | 703k | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE) |
4383 | 0 | { |
4384 | 0 | size_t end = obj->bitsize + obj->handlestream_size; |
4385 | 0 | LOG_HANDLE ( |
4386 | 0 | " hdl_dat: @%" PRIuSIZE ".%u - @%" PRIuSIZE ".%u (%" PRIuSIZE ")", |
4387 | 0 | bit8, hdl_dat->bit, end / 8, (unsigned)(end % 8), hdl_dat->size); |
4388 | 0 | } |
4389 | 703k | LOG_TRACE ("\n"); |
4390 | 703k | return 0; |
4391 | 703k | } |
4392 | | |
4393 | | /* The first common part of every entity. |
4394 | | |
4395 | | The last common part is common_entity_handle_data.spec |
4396 | | called by COMMON_ENTITY_HANDLE_DATA in dwg.spec |
4397 | | |
4398 | | For EED check page 269, par 28 (Extended Object Data) |
4399 | | For proxy graphics check page 270, par 29 (Proxy Entity Graphics) |
4400 | | |
4401 | | PRE(R_13b1) goes into decode_entity_preR13 instead. |
4402 | | */ |
4403 | | int |
4404 | | dwg_decode_entity (Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, |
4405 | | Dwg_Object_Entity *restrict ent) |
4406 | 783k | { |
4407 | 783k | int error = 0; |
4408 | 783k | Dwg_Data *dwg = ent->dwg; |
4409 | 783k | Dwg_Object *obj = &dwg->object[ent->objid]; |
4410 | 783k | Dwg_Object_Entity *_obj = ent; |
4411 | 783k | Dwg_Object_Entity *_ent = ent; |
4412 | 783k | size_t objectpos = bit_position (dat); |
4413 | 783k | int has_wrong_bitsize = 0; |
4414 | | |
4415 | | // obj->dat_address = dat->byte; // the data stream offset |
4416 | 783k | obj->bitsize_pos = objectpos; // absolute. needed for encode |
4417 | 783k | VERSIONS (R_2000, R_2007) |
4418 | 147k | { |
4419 | 147k | obj->bitsize = bit_read_RL (dat); // until the handles |
4420 | 147k | LOG_TRACE ("bitsize: " FORMAT_RL " [RL] @%" PRIuSIZE ".%u\n", obj->bitsize, |
4421 | 147k | dat->byte - 2, dat->bit); |
4422 | 147k | if (obj->bitsize > obj->size * 8) |
4423 | 126k | { |
4424 | 126k | LOG_ERROR ("Invalid bitsize " FORMAT_RL " > " FORMAT_RL, obj->bitsize, |
4425 | 126k | obj->size * 8); |
4426 | 126k | obj->bitsize = obj->size * 8; |
4427 | 126k | has_wrong_bitsize = 1; |
4428 | 126k | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
4429 | 126k | } |
4430 | 21.4k | else |
4431 | 21.4k | error |= obj_handle_stream (dat, obj, hdl_dat); |
4432 | 147k | } |
4433 | 783k | SINCE (R_2007a) |
4434 | 0 | { |
4435 | 0 | SINCE (R_2010b) |
4436 | 0 | { |
4437 | 0 | LOG_HANDLE (" bitsize: " FORMAT_RL ",", obj->bitsize); |
4438 | | // restrict the hdl_dat stream |
4439 | 0 | error |= obj_handle_stream (dat, obj, hdl_dat); |
4440 | 0 | } |
4441 | | // and set the string stream (restricted to size) |
4442 | | // skip for all types without strings |
4443 | 0 | if (obj->type >= 500 || obj_has_strings (obj->type)) |
4444 | 0 | error |= obj_string_stream (dat, obj, str_dat); |
4445 | 0 | else |
4446 | 0 | { |
4447 | 0 | bit_set_position (str_dat, obj->bitsize - 1); |
4448 | 0 | str_dat->size = 0; |
4449 | 0 | } |
4450 | 0 | } |
4451 | | |
4452 | 783k | error |= bit_read_H (dat, &(obj->handle)); |
4453 | 783k | if (error & DWG_ERR_INVALIDHANDLE || !obj->handle.value || !obj->handle.size) |
4454 | 439k | { |
4455 | 439k | LOG_ERROR ("Invalid object handle " FORMAT_H " at pos @%" PRIuSIZE ".%u", |
4456 | 439k | ARGS_H (obj->handle), dat->byte, dat->bit); |
4457 | | // TODO reconstruct the handle and search in the bitsoup? |
4458 | 439k | if (has_wrong_bitsize) |
4459 | 74.9k | obj->bitsize = 0; |
4460 | | // obj->handle.value = 0; |
4461 | | // obj->handle.size = 0; |
4462 | | // obj->handle.code = 0; |
4463 | 439k | ent->num_eed = 0; |
4464 | 439k | ent->preview_exists = 0; |
4465 | 439k | return error | DWG_ERR_INVALIDHANDLE; |
4466 | 439k | } |
4467 | 344k | LOG_TRACE ("handle: " FORMAT_H " [H 5]", ARGS_H (obj->handle)); |
4468 | 344k | LOG_INSANE (" @%" PRIuSIZE ".%u", dat->byte, dat->bit); |
4469 | 344k | LOG_TRACE ("\n"); |
4470 | | |
4471 | 344k | if (has_wrong_bitsize) |
4472 | 51.2k | LOG_WARN ("Skip eed"); |
4473 | 292k | else |
4474 | 292k | error |= dwg_decode_eed (dat, (Dwg_Object_Object *)ent); |
4475 | 344k | LOG_INSANE (" @%" PRIuSIZE ".%u\n", dat->byte, dat->bit); |
4476 | | // LOG_TRACE ("\n"); |
4477 | 344k | if (error & (DWG_ERR_INVALIDEED | DWG_ERR_VALUEOUTOFBOUNDS)) |
4478 | 276k | return error; |
4479 | | |
4480 | | // clang-format off |
4481 | 344k | #include "common_entity_data.spec" |
4482 | | // clang-format on |
4483 | | |
4484 | 67.9k | dwg_decode_common_entity_handle_data (dat, hdl_dat, obj); |
4485 | | |
4486 | | // elsewhere: object data, handles, padding bits, crc |
4487 | 67.9k | obj->common_size = bit_position (dat) - objectpos; |
4488 | 67.9k | LOG_HANDLE ("--common_size: %" PRIuSIZE "\n", |
4489 | 67.9k | obj->common_size); // needed for unknown |
4490 | | |
4491 | 67.9k | return error; |
4492 | 203k | } |
4493 | | |
4494 | | /* The first common part of every object. |
4495 | | |
4496 | | There is no COMMON_ENTITY_DATA for objects. |
4497 | | Check page 269, par 28 (Extended Object Data) |
4498 | | */ |
4499 | | int |
4500 | | dwg_decode_object (Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, |
4501 | | Dwg_Object_Object *restrict _obj) |
4502 | 3.96M | { |
4503 | 3.96M | int error = 0; |
4504 | 3.96M | Dwg_Data *dwg = _obj->dwg; |
4505 | 3.96M | Dwg_Object *obj = &dwg->object[_obj->objid]; |
4506 | 3.96M | size_t objectpos = bit_position (dat); |
4507 | 3.96M | int has_wrong_bitsize = 0; // first possibly fatal problem |
4508 | 3.96M | BITCODE_BL vcount; |
4509 | | |
4510 | | // obj->dat_address = dat->byte; // the data stream offset |
4511 | 3.96M | obj->bitsize_pos = objectpos; // absolute. needed for encode |
4512 | 3.96M | VERSIONS (R_2000, R_2007) |
4513 | 804k | { |
4514 | 804k | obj->bitsize = bit_read_RL (dat); |
4515 | 804k | LOG_TRACE ("bitsize: " FORMAT_RL " [RL] @%" PRIuSIZE ".%u\n", obj->bitsize, |
4516 | 804k | dat->byte - 2, dat->bit); |
4517 | 804k | if (obj->bitsize > obj->size * 8) |
4518 | 135k | { |
4519 | 135k | LOG_ERROR ("Invalid bitsize " FORMAT_RL " > " FORMAT_RL, obj->bitsize, |
4520 | 135k | obj->size * 8); |
4521 | 135k | obj->bitsize = obj->size * 8; |
4522 | 135k | has_wrong_bitsize = 1; |
4523 | 135k | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
4524 | 135k | } |
4525 | 668k | else |
4526 | 668k | error |= obj_handle_stream (dat, obj, hdl_dat); |
4527 | 804k | } |
4528 | 3.96M | SINCE (R_2007a) |
4529 | 0 | { |
4530 | 0 | SINCE (R_2010b) |
4531 | 0 | { |
4532 | 0 | LOG_HANDLE (" bitsize: " FORMAT_RL ",", obj->bitsize); |
4533 | 0 | } |
4534 | 0 | if (obj->bitsize > obj->size * 8) |
4535 | 0 | { |
4536 | 0 | obj->bitsize = obj->size * 8; |
4537 | 0 | has_wrong_bitsize = 1; |
4538 | 0 | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
4539 | 0 | LOG_HANDLE (" (fixed)"); |
4540 | 0 | } |
4541 | | // restrict the hdl_dat stream. already done for r2007 |
4542 | 0 | SINCE (R_2010b) |
4543 | 0 | { |
4544 | 0 | error |= obj_handle_stream (dat, obj, hdl_dat); |
4545 | 0 | } |
4546 | | // and set the string stream (restricted to size) |
4547 | 0 | if (obj->type >= 500 || obj_has_strings (obj->type)) |
4548 | 0 | error |= obj_string_stream (dat, obj, str_dat); |
4549 | 0 | else |
4550 | 0 | { |
4551 | 0 | str_dat->chain += str_dat->byte; |
4552 | 0 | str_dat->byte = 0; |
4553 | 0 | str_dat->bit = 0; |
4554 | 0 | bit_advance_position (str_dat, obj->bitsize - 1 - 8); |
4555 | 0 | str_dat->size = 0; |
4556 | 0 | } |
4557 | 0 | } |
4558 | 3.96M | SINCE (R_13b1) |
4559 | 3.92M | { |
4560 | 3.92M | error |= bit_read_H (dat, &obj->handle); |
4561 | 3.92M | if (error & DWG_ERR_INVALIDHANDLE || !obj->handle.value |
4562 | 518k | || !obj->handle.size || obj->handle.code) |
4563 | 3.77M | { |
4564 | 3.77M | LOG_ERROR ("Invalid object handle " FORMAT_H " at pos @%" PRIuSIZE |
4565 | 3.77M | ".%u", |
4566 | 3.77M | ARGS_H (obj->handle), dat->byte, dat->bit); |
4567 | | // TODO reconstruct the handle and search in the bitsoup? |
4568 | 3.77M | if (has_wrong_bitsize) |
4569 | 121k | obj->bitsize = 0; |
4570 | 3.77M | obj->tio.object->num_eed = 0; |
4571 | 3.77M | return error | DWG_ERR_INVALIDHANDLE; |
4572 | 3.77M | } |
4573 | 153k | LOG_TRACE ("handle: " FORMAT_H " [H 5]\n", ARGS_H (obj->handle)); |
4574 | 153k | } |
4575 | | |
4576 | 191k | SINCE (R_13b1) |
4577 | 153k | { |
4578 | 153k | if (has_wrong_bitsize) |
4579 | 14.4k | LOG_WARN ("Skip eed"); |
4580 | 139k | else |
4581 | 139k | error |= dwg_decode_eed (dat, _obj); |
4582 | 153k | if (error & (DWG_ERR_INVALIDEED | DWG_ERR_VALUEOUTOFBOUNDS)) |
4583 | 119k | return error; |
4584 | 153k | } |
4585 | | |
4586 | 72.3k | VERSIONS (R_13b1, R_14) |
4587 | 20.4k | { |
4588 | 20.4k | obj->bitsize = bit_read_RL (dat); |
4589 | 20.4k | LOG_TRACE ("bitsize: %u [RL]\n", obj->bitsize); |
4590 | 20.4k | if (obj->bitsize > obj->size * 8) |
4591 | 14.6k | { |
4592 | 14.6k | LOG_ERROR ("Invalid bitsize " FORMAT_RL " > " FORMAT_RL, obj->bitsize, |
4593 | 14.6k | obj->size * 8); |
4594 | 14.6k | obj->bitsize = obj->size * 8; |
4595 | 14.6k | has_wrong_bitsize = 1; |
4596 | 14.6k | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
4597 | 14.6k | } |
4598 | 5.84k | else |
4599 | 5.84k | error |= obj_handle_stream (dat, obj, hdl_dat); |
4600 | 20.4k | } |
4601 | | |
4602 | | // clang-format off |
4603 | 72.3k | #include "common_object_handle_data.spec" |
4604 | | // clang-format on |
4605 | | |
4606 | 57.8k | obj->common_size = bit_position (dat) - objectpos; |
4607 | 57.8k | LOG_HANDLE ("--common_size: %" PRIuSIZE "\n", |
4608 | 57.8k | obj->common_size); // needed for unknown |
4609 | | |
4610 | 57.8k | return error; |
4611 | 58.0k | } |
4612 | | |
4613 | | static int |
4614 | | dwg_decode_add_object_ref (Dwg_Data *restrict dwg, Dwg_Object_Ref *ref) |
4615 | 33.7M | { |
4616 | 33.7M | Dwg_Object_Ref **object_ref_old = dwg->object_ref; |
4617 | | |
4618 | | // Reserve memory space for object references |
4619 | 33.7M | if (!dwg->num_object_refs) |
4620 | 23.1k | { |
4621 | 23.1k | BITCODE_RLL max_refs = dwg->header_vars.HANDSEED |
4622 | 23.1k | ? dwg->header_vars.HANDSEED->absolute_ref |
4623 | 23.1k | : REFS_PER_REALLOC; |
4624 | 23.1k | if (max_refs < REFS_PER_REALLOC) |
4625 | 4.02k | max_refs = REFS_PER_REALLOC; |
4626 | 23.1k | dwg->object_ref |
4627 | 23.1k | = (Dwg_Object_Ref **)calloc (max_refs, sizeof (Dwg_Object_Ref *)); |
4628 | 23.1k | } |
4629 | 33.7M | else if (dwg->num_object_refs % REFS_PER_REALLOC == 0) |
4630 | 1.08k | { |
4631 | 1.08k | dwg->object_ref = (Dwg_Object_Ref **)realloc ( |
4632 | 1.08k | dwg->object_ref, (dwg->num_object_refs + REFS_PER_REALLOC) |
4633 | 1.08k | * sizeof (Dwg_Object_Ref *)); |
4634 | 1.08k | memset (&dwg->object_ref[dwg->num_object_refs], 0, |
4635 | 1.08k | REFS_PER_REALLOC * sizeof (Dwg_Object_Ref *)); |
4636 | 1.08k | dwg->dirty_refs = 1; |
4637 | 1.08k | LOG_TRACE ("REALLOC dwg->object_ref vector to %u\n", |
4638 | 1.08k | dwg->num_object_refs + REFS_PER_REALLOC); |
4639 | 1.08k | } |
4640 | 33.7M | if (!dwg->object_ref) |
4641 | 0 | { |
4642 | 0 | LOG_ERROR ("Out of memory"); |
4643 | 0 | dwg->object_ref = object_ref_old; |
4644 | 0 | return DWG_ERR_OUTOFMEM; |
4645 | 0 | } |
4646 | 33.7M | dwg->object_ref[dwg->num_object_refs++] = ref; |
4647 | 33.7M | ref->handleref.is_global = 1; |
4648 | 33.7M | return 0; |
4649 | 33.7M | } |
4650 | | |
4651 | | /* Returns a freshly allocated ref */ |
4652 | | EXPORT Dwg_Object_Ref * |
4653 | | dwg_new_ref (Dwg_Data *restrict dwg) |
4654 | 3.02M | { |
4655 | 3.02M | Dwg_Object_Ref *ref = (Dwg_Object_Ref *)calloc (1, sizeof (Dwg_Object_Ref)); |
4656 | 3.02M | if (!ref) |
4657 | 0 | { |
4658 | 0 | LOG_ERROR ("Out of memory"); |
4659 | 0 | return NULL; |
4660 | 0 | } |
4661 | 3.02M | if (dwg_decode_add_object_ref (dwg, ref)) |
4662 | 0 | { |
4663 | 0 | free (ref); |
4664 | 0 | LOG_INSANE ("dwg_decode_add_object_ref failed " FORMAT_BL "\n", |
4665 | 0 | dwg->num_object_refs); |
4666 | 0 | return NULL; |
4667 | 0 | } |
4668 | 3.02M | return ref; |
4669 | 3.02M | } |
4670 | | |
4671 | | /* Store an object reference in a separate dwg->object_ref array |
4672 | | which is the id for handles, i.e. DXF 5, 330. */ |
4673 | | Dwg_Object_Ref * |
4674 | | dwg_decode_handleref (Bit_Chain *restrict dat, Dwg_Object *restrict obj, |
4675 | | Dwg_Data *restrict dwg) |
4676 | 19.4k | { |
4677 | | // Welcome to the house of evil code |
4678 | 19.4k | Dwg_Object_Ref *ref = (Dwg_Object_Ref *)calloc (1, sizeof (Dwg_Object_Ref)); |
4679 | 19.4k | if (!ref) |
4680 | 0 | { |
4681 | 0 | LOG_ERROR ("Out of memory"); |
4682 | 0 | return NULL; |
4683 | 0 | } |
4684 | 19.4k | if (bit_read_H (dat, &ref->handleref)) |
4685 | 6.94k | { |
4686 | 6.94k | free (ref); |
4687 | 6.94k | return NULL; |
4688 | 6.94k | } |
4689 | | |
4690 | | // If the handle size is 0 and not a relative handle, it is probably a null |
4691 | | // handle. It shouldn't be placed in the object ref vector. |
4692 | 12.5k | if (ref->handleref.size || (obj && ref->handleref.code > 5)) |
4693 | 6.95k | { |
4694 | 6.95k | if (dwg_decode_add_object_ref (dwg, ref)) |
4695 | 0 | { |
4696 | 0 | free (ref); |
4697 | 0 | return NULL; |
4698 | 0 | } |
4699 | 6.95k | } |
4700 | 5.55k | else if (!ref->handleref.value) |
4701 | 5.55k | { |
4702 | 5.55k | if (obj) |
4703 | 161 | { |
4704 | 161 | free (ref); |
4705 | 161 | return NULL; |
4706 | 161 | } |
4707 | 5.39k | ref->absolute_ref = 0; |
4708 | 5.39k | ref->obj = NULL; |
4709 | 5.39k | return ref; |
4710 | 5.55k | } |
4711 | | |
4712 | | // We receive a null obj when we are reading |
4713 | | // handles in the header variables section |
4714 | 6.95k | if (!obj) |
4715 | 6.80k | { |
4716 | 6.80k | if (ref->handleref.value) |
4717 | 6.76k | { |
4718 | 6.76k | ref->absolute_ref = ref->handleref.value; |
4719 | 6.76k | ref->obj = NULL; |
4720 | 6.76k | return ref; |
4721 | 6.76k | } |
4722 | 35 | if (ref->handleref.code >= 6) |
4723 | 5 | { |
4724 | 5 | LOG_ERROR ("Empty obj argument for handleref code %d", |
4725 | 5 | ref->handleref.code); |
4726 | 5 | ref->obj = NULL; |
4727 | 5 | return NULL; |
4728 | 5 | } |
4729 | 35 | } |
4730 | | |
4731 | | /* |
4732 | | * With TYPEDOBJHANDLE 2-5 the code indicates the type of ownership. |
4733 | | * With OFFSETOBJHANDLE >5 the handle is stored as an offset from some other |
4734 | | * handle. |
4735 | | */ |
4736 | 184 | switch (ref->handleref.code) |
4737 | 184 | { |
4738 | 0 | case 6: |
4739 | 0 | ref->absolute_ref = (obj->handle.value + 1); |
4740 | 0 | break; |
4741 | 0 | case 8: |
4742 | 0 | ref->absolute_ref = (obj->handle.value - 1); |
4743 | 0 | break; |
4744 | 20 | case 10: |
4745 | 20 | ref->absolute_ref = (obj->handle.value + ref->handleref.value); |
4746 | 20 | break; |
4747 | 14 | case 12: |
4748 | 14 | ref->absolute_ref = (obj->handle.value - ref->handleref.value); |
4749 | 14 | break; |
4750 | 0 | case 14: // eg 2007 REGION.history_id (some very high number) |
4751 | 0 | ref->absolute_ref = obj->handle.value; |
4752 | 0 | break; |
4753 | 19 | case 2: |
4754 | 33 | case 3: |
4755 | 35 | case 4: |
4756 | 48 | case 5: |
4757 | 48 | ref->absolute_ref = ref->handleref.value; |
4758 | 48 | break; |
4759 | 25 | case 0: // ignore? |
4760 | 25 | ref->absolute_ref = ref->handleref.value; |
4761 | 25 | break; |
4762 | 77 | default: |
4763 | | // dwg->object_ref[dwg->num_object_refs-1] = NULL; |
4764 | | // dwg->num_object_refs--; |
4765 | 77 | ref->absolute_ref = 0; |
4766 | 77 | ref->obj = NULL; |
4767 | 77 | LOG_WARN ("Invalid handle pointer code %d", ref->handleref.code); |
4768 | 77 | break; |
4769 | 184 | } |
4770 | 184 | return ref; |
4771 | 184 | } |
4772 | | |
4773 | | /** |
4774 | | * code: |
4775 | | * TYPEDOBJHANDLE: |
4776 | | * 2 Soft owner |
4777 | | * 3 Hard owner |
4778 | | * 4 Soft pointer |
4779 | | * 5 Hard pointer |
4780 | | * OFFSETOBJHANDLE for soft owners or pointers: |
4781 | | * 6 ref + 1 |
4782 | | * 8 ref - 1 |
4783 | | * a ref + offset |
4784 | | * c ref - offset |
4785 | | * e ?? |
4786 | | */ |
4787 | | Dwg_Object_Ref * |
4788 | | dwg_decode_handleref_with_code (Bit_Chain *restrict dat, |
4789 | | Dwg_Object *restrict obj, |
4790 | | Dwg_Data *restrict dwg, unsigned int code) |
4791 | 149M | { |
4792 | 149M | Dwg_Object_Ref *ref = (Dwg_Object_Ref *)calloc (1, sizeof (Dwg_Object_Ref)); |
4793 | 149M | if (!ref) |
4794 | 0 | { |
4795 | 0 | LOG_ERROR ("Out of memory"); |
4796 | 0 | return NULL; |
4797 | 0 | } |
4798 | 149M | if (bit_read_H (dat, &ref->handleref)) |
4799 | 78.7M | { |
4800 | 78.7M | free (ref); |
4801 | 78.7M | return NULL; |
4802 | 78.7M | } |
4803 | | |
4804 | | /* If the handle size is 0 and not a relative handle, it is probably |
4805 | | a null handle. |
4806 | | It shouldn't be placed in the object ref vector, |
4807 | | just with indxf the NULL HDL is. */ |
4808 | 71.1M | if (ref->handleref.size || (obj && ref->handleref.code > 5)) |
4809 | 30.7M | { |
4810 | 30.7M | if (dwg_decode_add_object_ref (dwg, ref)) |
4811 | 0 | { |
4812 | 0 | free (ref); |
4813 | 0 | return NULL; |
4814 | 0 | } |
4815 | 30.7M | } |
4816 | 40.4M | else if (!ref->handleref.value) |
4817 | 40.4M | { |
4818 | | /*if (obj) |
4819 | | { |
4820 | | free (ref); |
4821 | | return NULL; |
4822 | | } |
4823 | | */ |
4824 | 40.4M | ref->absolute_ref = 0; |
4825 | 40.4M | ref->obj = NULL; |
4826 | 40.4M | return ref; |
4827 | 40.4M | } |
4828 | | |
4829 | | // We receive a null obj when we are reading |
4830 | | // handles in the header variables section |
4831 | 30.7M | if (!obj) |
4832 | 120k | { |
4833 | 120k | ref->absolute_ref = ref->handleref.value; |
4834 | 120k | ref->obj = NULL; |
4835 | 120k | return ref; |
4836 | 120k | } |
4837 | | |
4838 | | /* |
4839 | | * With TYPEDOBJHANDLE 2-5 the code indicates the type of ownership. |
4840 | | * With OFFSETOBJHANDLE >5 the handle is stored as an offset from some other |
4841 | | * handle. |
4842 | | */ |
4843 | 30.5M | switch (ref->handleref.code) |
4844 | 30.5M | { |
4845 | 908k | case 0x06: |
4846 | 908k | ref->absolute_ref = (obj->handle.value + 1); |
4847 | 908k | break; |
4848 | 4.21M | case 0x08: |
4849 | 4.21M | ref->absolute_ref = (obj->handle.value - 1); |
4850 | 4.21M | break; |
4851 | 1.27M | case 0x0A: |
4852 | 1.27M | ref->absolute_ref = (obj->handle.value + ref->handleref.value); |
4853 | 1.27M | break; |
4854 | 2.13M | case 0x0C: |
4855 | 2.13M | ref->absolute_ref = (obj->handle.value - ref->handleref.value); |
4856 | 2.13M | break; |
4857 | 750k | case 0x0E: // eg 2007 REGION.history_id (some very high number) |
4858 | 750k | ref->absolute_ref = obj->handle.value; |
4859 | 750k | break; |
4860 | 895k | case 2: |
4861 | 2.24M | case 3: |
4862 | 4.46M | case 4: |
4863 | 6.04M | case 5: |
4864 | 6.04M | ref->absolute_ref = ref->handleref.value; |
4865 | 6.04M | break; |
4866 | 8.27M | case 0: // ignore? |
4867 | 8.27M | ref->absolute_ref = ref->handleref.value; |
4868 | 8.27M | break; |
4869 | 6.99M | default: |
4870 | | // dwg->object_ref[dwg->num_object_refs-1] = NULL; |
4871 | | // dwg->num_object_refs--; |
4872 | 6.99M | ref->absolute_ref = 0; |
4873 | 6.99M | ref->obj = NULL; |
4874 | 6.99M | LOG_WARN ("Invalid handle pointer code %d", ref->handleref.code); |
4875 | 6.99M | break; |
4876 | 30.5M | } |
4877 | 30.5M | return ref; |
4878 | 30.5M | } |
4879 | | |
4880 | | AFL_GCC_TOOBIG |
4881 | | int |
4882 | | dwg_decode_header_variables (Bit_Chain *dat, Bit_Chain *hdl_dat, |
4883 | | Bit_Chain *str_dat, Dwg_Data *restrict dwg) |
4884 | 19.4k | { |
4885 | 19.4k | Dwg_Header_Variables *_obj = &dwg->header_vars; |
4886 | 19.4k | Dwg_Object *obj = NULL; |
4887 | 19.4k | int error = 0; |
4888 | | |
4889 | | // clang-format off |
4890 | 877k | #include "header_variables.spec" |
4891 | | // clang-format on |
4892 | | |
4893 | 877k | if (!dwg->header_vars.BLOCK_RECORD_MSPACE) |
4894 | 3.88k | return error | DWG_ERR_INVALIDDWG; |
4895 | 8.67k | return error; |
4896 | 877k | } |
4897 | | AFL_GCC_POP |
4898 | | |
4899 | | static int |
4900 | | dwg_decode_common_entity_handle_data (Bit_Chain *dat, Bit_Chain *hdl_dat, |
4901 | | Dwg_Object *restrict obj) |
4902 | 67.9k | { |
4903 | | |
4904 | 67.9k | Dwg_Data *dwg = obj->parent; |
4905 | 67.9k | Dwg_Object_Entity *_obj, *_ent; |
4906 | 67.9k | BITCODE_BL vcount; |
4907 | 67.9k | int error = 0; |
4908 | | |
4909 | 67.9k | _obj = _ent = obj->tio.entity; |
4910 | | |
4911 | | // deferred from common_entity_data, which has no hdl_dat |
4912 | 67.9k | if (dat->from_version >= R_2007 && _ent->color.flag & 0x40) |
4913 | 67.9k | FIELD_HANDLE (color.handle, 0, |
4914 | 67.9k | 430); // lgtm[cpp/use-after-free] codeql[cpp/use-after-free] |
4915 | | |
4916 | | // clang-format off |
4917 | 67.9k | #include "common_entity_handle_data.spec" |
4918 | | // clang-format on |
4919 | | |
4920 | 36.9k | return error; |
4921 | 42.8k | } |
4922 | | |
4923 | | void |
4924 | | dwg_free_xdata_resbuf (Dwg_Resbuf *rbuf) |
4925 | 8.12k | { |
4926 | 14.6k | while (rbuf) |
4927 | 6.53k | { |
4928 | 6.53k | Dwg_Resbuf *next = rbuf->nextrb; |
4929 | 6.53k | short type = dwg_resbuf_value_type (rbuf->type); |
4930 | 6.53k | if (type == DWG_VT_STRING || type == DWG_VT_BINARY) |
4931 | 579 | free (rbuf->value.str.u.data); |
4932 | 6.53k | free (rbuf); |
4933 | 6.53k | rbuf = next; |
4934 | 6.53k | } |
4935 | 8.12k | } |
4936 | | |
4937 | | // TODO: unify with eed[], use an array not linked list. |
4938 | | Dwg_Resbuf * |
4939 | | dwg_decode_xdata (Bit_Chain *restrict dat, Dwg_Object_XRECORD *restrict obj, |
4940 | | BITCODE_BL xdata_size) |
4941 | 5.61k | { |
4942 | 5.61k | Dwg_Resbuf *rbuf, *root = NULL, *curr = NULL; |
4943 | 5.61k | size_t start_address, end_address, curr_address; |
4944 | 5.61k | BITCODE_BL i, num_xdata = 0; |
4945 | 5.61k | BITCODE_RS length; |
4946 | | |
4947 | 5.61k | start_address = dat->byte; |
4948 | 5.61k | end_address = start_address + (size_t)xdata_size; |
4949 | 5.61k | if (obj->parent && obj->parent->objid) |
4950 | 5.60k | { |
4951 | 5.60k | Dwg_Data *dwg = obj->parent->dwg; |
4952 | 5.60k | Dwg_Object *o = &dwg->object[obj->parent->objid]; |
4953 | 5.60k | if (end_address > o->size) |
4954 | 1.19k | { |
4955 | 1.19k | LOG_WARN ("Invalid XRECORD.xdata_size " FORMAT_BL, xdata_size); |
4956 | 1.19k | if ((o->bitsize / 8) <= (BITCODE_RL)start_address) |
4957 | 1.04k | { |
4958 | | // fuzzers only |
4959 | 1.04k | LOG_ERROR ("No room for xdata size:" FORMAT_RL |
4960 | 1.04k | " <= pos:" FORMAT_RL, |
4961 | 1.04k | (o->bitsize / 8), (BITCODE_RL)start_address); |
4962 | 1.04k | obj->xdata_size = 0; |
4963 | 1.04k | return NULL; |
4964 | 1.04k | } |
4965 | | // Possible ACAD bug. Calculate by ourselves |
4966 | 151 | xdata_size = (BITCODE_BL)((o->bitsize / 8) - start_address); |
4967 | 151 | LOG_INFO ("calc xdata_size => " FORMAT_BL "\n", xdata_size); |
4968 | 151 | obj->xdata_size = xdata_size; |
4969 | 151 | end_address = start_address + (size_t)xdata_size; |
4970 | 151 | } |
4971 | 5.60k | } |
4972 | 4.57k | if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) |
4973 | 0 | { |
4974 | 0 | LOG_INSANE ("XDATA size: " FORMAT_BL " (end @%" PRIuSIZE ")\n", |
4975 | 0 | xdata_size, end_address); |
4976 | 0 | LOG_INSANE_TF (&dat->chain[dat->byte], (int)xdata_size); |
4977 | 0 | } |
4978 | 4.57k | curr_address = dat->byte; |
4979 | | |
4980 | 8.59k | while (dat->byte < end_address) |
4981 | 8.17k | { |
4982 | 8.17k | enum RESBUF_VALUE_TYPE vtype; |
4983 | 8.17k | rbuf = (Dwg_Resbuf *)calloc (1, sizeof (Dwg_Resbuf)); |
4984 | 8.17k | if (!rbuf) |
4985 | 0 | { |
4986 | 0 | LOG_ERROR ("Out of memory"); |
4987 | 0 | dwg_free_xdata_resbuf (root); |
4988 | 0 | return NULL; |
4989 | 0 | } |
4990 | 8.17k | rbuf->nextrb = NULL; |
4991 | 8.17k | rbuf->type = bit_read_RS (dat); |
4992 | 8.17k | LOG_HANDLE (" xdata[%u] type: " FORMAT_RS " [RS]\n", num_xdata, |
4993 | 8.17k | rbuf->type); |
4994 | 8.17k | if (dat->byte == curr_address || dat->byte >= end_address) |
4995 | 472 | { |
4996 | | // no advance, by dat overflow |
4997 | 472 | free (rbuf); |
4998 | 472 | dat->byte = end_address; |
4999 | 472 | break; |
5000 | 472 | } |
5001 | 7.69k | if (rbuf->type < 0 || rbuf->type >= 2000) |
5002 | 1.16k | { |
5003 | 1.16k | LOG_ERROR ("Invalid xdata type %d [RS]", rbuf->type); |
5004 | 1.16k | free (rbuf); |
5005 | 1.16k | dat->byte = end_address; |
5006 | 1.16k | break; |
5007 | 1.16k | } |
5008 | 6.53k | vtype = dwg_resbuf_value_type (rbuf->type); |
5009 | 6.53k | switch (vtype) |
5010 | 6.53k | { |
5011 | 547 | case DWG_VT_STRING: |
5012 | 547 | PRE (R_2007a) |
5013 | 547 | { |
5014 | 547 | length = bit_read_RS (dat); |
5015 | 547 | LOG_INSANE ("xdata[%u]: length " FORMAT_RS "\n", num_xdata, |
5016 | 547 | length); |
5017 | 547 | rbuf->value.str.codepage = bit_read_RC (dat); |
5018 | 547 | LOG_INSANE ("xdata[%u]: codepage %u\n", num_xdata, |
5019 | 547 | (unsigned)rbuf->value.str.codepage); |
5020 | 547 | if (dat->byte + length > end_address || (short)length < 0) |
5021 | 480 | break; |
5022 | 67 | rbuf->value.str.is_tu = 0; |
5023 | 67 | rbuf->value.str.size = length; |
5024 | 67 | rbuf->value.str.u.data = (char *)bit_read_TF (dat, length); |
5025 | 67 | LOG_INSANE ("STRING "); |
5026 | 67 | LOG_TRACE ("xdata[%u]: \"%s\" [TV %d]\n", num_xdata, |
5027 | 67 | rbuf->value.str.u.data, rbuf->type); |
5028 | 67 | } |
5029 | 0 | LATER_VERSIONS |
5030 | 0 | { |
5031 | 0 | length = bit_read_RS (dat); |
5032 | 0 | if ((short)length > 0 && dat->byte + (length * 2) <= end_address) |
5033 | 0 | { |
5034 | 0 | rbuf->value.str.u.wdata = (BITCODE_TU)calloc (length + 1, 2); |
5035 | 0 | if (!rbuf->value.str.u.wdata) |
5036 | 0 | { |
5037 | 0 | LOG_ERROR ("Out of memory"); |
5038 | 0 | obj->xdata_size = 0; |
5039 | 0 | obj->num_xdata = 0; |
5040 | 0 | if (root) |
5041 | 0 | { |
5042 | 0 | dwg_free_xdata_resbuf (root); |
5043 | 0 | if (rbuf) |
5044 | 0 | free (rbuf); |
5045 | 0 | } |
5046 | 0 | else |
5047 | 0 | dwg_free_xdata_resbuf (rbuf); |
5048 | 0 | return NULL; |
5049 | 0 | } |
5050 | 0 | rbuf->value.str.is_tu = 1; |
5051 | 0 | rbuf->value.str.size = length; |
5052 | 0 | for (i = 0; i < length; i++) |
5053 | 0 | rbuf->value.str.u.wdata[i] = bit_read_RS (dat); |
5054 | 0 | rbuf->value.str.u.wdata[i] = '\0'; |
5055 | 0 | LOG_INSANE ("UNISTRING "); |
5056 | 0 | LOG_TRACE_TU ("xdata", rbuf->value.str.u.wdata, rbuf->type); |
5057 | 0 | } |
5058 | 0 | else |
5059 | 0 | { |
5060 | 0 | rbuf->value.str.size = 0; |
5061 | 0 | } |
5062 | 0 | } |
5063 | 67 | break; |
5064 | 67 | case DWG_VT_REAL: |
5065 | 49 | if (dat->byte + 8 > end_address) |
5066 | 46 | break; |
5067 | 3 | rbuf->value.dbl = bit_read_RD (dat); |
5068 | 3 | LOG_TRACE ("xdata[%u]: %f [RD %d]\n", num_xdata, rbuf->value.dbl, |
5069 | 3 | rbuf->type); |
5070 | 3 | break; |
5071 | 0 | case DWG_VT_BOOL: |
5072 | 89 | case DWG_VT_INT8: |
5073 | 89 | if (dat->byte + 1 > end_address) |
5074 | 0 | break; |
5075 | 89 | rbuf->value.i8 = bit_read_RC (dat); |
5076 | 89 | LOG_TRACE ("xdata[%u]: %d [RC %d]\n", num_xdata, (int)rbuf->value.i8, |
5077 | 89 | rbuf->type); |
5078 | 89 | break; |
5079 | 41 | case DWG_VT_INT16: |
5080 | 41 | if (dat->byte + 2 > end_address) |
5081 | 3 | break; |
5082 | 38 | rbuf->value.i16 = (short)bit_read_RS (dat); |
5083 | 38 | LOG_TRACE ("xdata[%u]: %d [RS %d]\n", num_xdata, |
5084 | 38 | (int)rbuf->value.i16, rbuf->type); |
5085 | 38 | break; |
5086 | 187 | case DWG_VT_INT32: |
5087 | 187 | if (dat->byte + 4 > end_address) |
5088 | 0 | break; |
5089 | 187 | rbuf->value.i32 = (int32_t)bit_read_RL (dat); |
5090 | 187 | LOG_TRACE ("xdata[%u]: %d [RLd %d]\n", num_xdata, |
5091 | 187 | (int)rbuf->value.i32, rbuf->type); |
5092 | 187 | break; |
5093 | 10 | case DWG_VT_INT64: |
5094 | 10 | if (dat->byte + 8 > end_address) |
5095 | 8 | break; |
5096 | 2 | rbuf->value.i64 = (int64_t)bit_read_RLL (dat); |
5097 | 2 | LOG_TRACE ("xdata[%u]: " FORMAT_RLLd " [RLLd %d]\n", num_xdata, |
5098 | 2 | rbuf->value.i64, rbuf->type); |
5099 | 2 | break; |
5100 | 3.00k | case DWG_VT_POINT3D: |
5101 | 3.00k | if (dat->byte + 24 > end_address) |
5102 | 1.03k | break; |
5103 | 1.97k | rbuf->value.pt[0] = bit_read_RD (dat); |
5104 | 1.97k | rbuf->value.pt[1] = bit_read_RD (dat); |
5105 | 1.97k | rbuf->value.pt[2] = bit_read_RD (dat); |
5106 | 1.97k | LOG_TRACE ("xdata[%u]: %f,%f,%f [3RD %d]\n", num_xdata, |
5107 | 1.97k | rbuf->value.pt[0], rbuf->value.pt[1], rbuf->value.pt[2], |
5108 | 1.97k | rbuf->type); |
5109 | 1.97k | break; |
5110 | 32 | case DWG_VT_BINARY: |
5111 | 32 | rbuf->value.str.size = bit_read_RC (dat); |
5112 | 32 | if (dat->byte + rbuf->value.str.size > end_address) |
5113 | 32 | { |
5114 | 32 | LOG_ERROR ("Invalid XDATA BINARY size %u", |
5115 | 32 | (unsigned)rbuf->value.str.size); |
5116 | 32 | rbuf->value.str.size = 0; |
5117 | 32 | break; |
5118 | 32 | } |
5119 | 0 | rbuf->value.str.u.data |
5120 | 0 | = (char *)bit_read_TF (dat, rbuf->value.str.size); |
5121 | 0 | LOG_INSANE ("BINARY "); |
5122 | 0 | LOG_TRACE ("xdata[%u]: [TF %d %d] ", num_xdata, rbuf->value.str.size, |
5123 | 0 | rbuf->type); |
5124 | 0 | LOG_TRACE_TF (rbuf->value.str.u.data, rbuf->value.str.size); |
5125 | 0 | break; |
5126 | 62 | case DWG_VT_HANDLE: |
5127 | 62 | case DWG_VT_OBJECTID: |
5128 | 62 | if (dat->byte + 8 > end_address) |
5129 | 14 | break; |
5130 | 48 | rbuf->value.absref = bit_read_RLL (dat); |
5131 | 48 | LOG_TRACE ("xdata[%u]: " FORMAT_HV " [H %d]\n", num_xdata, |
5132 | 48 | rbuf->value.absref, rbuf->type); |
5133 | 48 | break; |
5134 | 2.51k | case DWG_VT_INVALID: |
5135 | 2.51k | default: |
5136 | 2.51k | LOG_ERROR ("Invalid group code in xdata[%u]: %d", num_xdata, |
5137 | 2.51k | rbuf->type); |
5138 | 2.51k | LOG_WARN ("xdata read %" PRIuSIZE ", expected %d", |
5139 | 2.51k | dat->byte - start_address, obj->xdata_size); |
5140 | 2.51k | dwg_free_xdata_resbuf (rbuf); |
5141 | 2.51k | if (curr) |
5142 | 1.02k | curr->nextrb = NULL; |
5143 | 2.51k | dat->byte = end_address; |
5144 | 2.51k | obj->num_xdata = num_xdata; |
5145 | 2.51k | return root; |
5146 | 6.53k | } |
5147 | 4.02k | num_xdata++; |
5148 | | |
5149 | 4.02k | if (!curr) |
5150 | 2.19k | { |
5151 | 2.19k | curr = root = rbuf; |
5152 | 2.19k | } |
5153 | 1.82k | else |
5154 | 1.82k | { |
5155 | 1.82k | curr->nextrb = rbuf; |
5156 | 1.82k | curr = rbuf; |
5157 | 1.82k | } |
5158 | 4.02k | curr_address = dat->byte; |
5159 | 4.02k | } |
5160 | 2.05k | if (dat->byte - start_address != obj->xdata_size) |
5161 | 14 | LOG_WARN ("xdata read %" PRIuSIZE ", expected %d", |
5162 | 2.05k | dat->byte - start_address, obj->xdata_size); |
5163 | 2.05k | obj->num_xdata = num_xdata; |
5164 | 2.05k | return root; |
5165 | 4.57k | } |
5166 | | |
5167 | | static BITCODE_BB |
5168 | | bit_read_BB_noadv (Bit_Chain *dat) |
5169 | 1.51M | { |
5170 | 1.51M | unsigned char result; |
5171 | 1.51M | unsigned char byte; |
5172 | | |
5173 | 1.51M | if (dat->byte >= dat->size) |
5174 | 187k | { |
5175 | 187k | LOG_ERROR ("%s buffer overflow at %" PRIuSIZE " >= %" PRIuSIZE, |
5176 | 187k | __FUNCTION__, dat->byte, dat->size); |
5177 | 187k | return 9; |
5178 | 187k | } |
5179 | 1.32M | byte = dat->chain[dat->byte]; |
5180 | 1.32M | if (dat->bit < 7) |
5181 | 1.32M | result = (byte & (0xc0 >> dat->bit)) >> (6 - dat->bit); |
5182 | 0 | else |
5183 | 0 | { |
5184 | 0 | result = (byte & 0x01) << 1; |
5185 | 0 | if (dat->byte < dat->size - 1) |
5186 | 0 | { |
5187 | 0 | byte = dat->chain[dat->byte + 1]; |
5188 | 0 | result |= (byte & 0x80) >> 7; |
5189 | 0 | } |
5190 | 0 | } |
5191 | 1.32M | return (BITCODE_BB)result; |
5192 | 1.51M | } |
5193 | | |
5194 | | /* OBJECTS *******************************************************************/ |
5195 | | |
5196 | | #include "dwg.spec" |
5197 | | |
5198 | | /* Forward declarations for functions generated from dwg2.spec in decode2.c. |
5199 | | Uses objects.inc which also covers first-half (static) functions, so |
5200 | | suppress the redundant-decls warning for those. */ |
5201 | | #undef DWG_ENTITY |
5202 | | #undef DWG_ENTITY_END |
5203 | | #undef DWG_OBJECT |
5204 | | #undef DWG_OBJECT_END |
5205 | | GCC46_DIAG_IGNORE (-Wredundant-decls) |
5206 | | #define DWG_ENTITY(token) \ |
5207 | | extern int dwg_decode_##token (Bit_Chain *restrict dat, \ |
5208 | | Dwg_Object *restrict obj); |
5209 | | #define DWG_ENTITY_END |
5210 | | #define DWG_OBJECT(token) \ |
5211 | | extern int dwg_decode_##token (Bit_Chain *restrict dat, \ |
5212 | | Dwg_Object *restrict obj); |
5213 | | #define DWG_OBJECT_END |
5214 | | #include "objects.inc" |
5215 | | GCC46_DIAG_RESTORE |
5216 | | |
5217 | | /*-------------------------------------------------------------------------------- |
5218 | | * Private functions which depend on the preceding |
5219 | | */ |
5220 | | |
5221 | | /* check the types of all referenced handles. |
5222 | | r2010+ often mix up the hdlstream offset: |
5223 | | layer,vertex*,seqend. check the types then also. |
5224 | | */ |
5225 | | static void |
5226 | | check_POLYLINE_handles (Dwg_Object *obj) |
5227 | 0 | { |
5228 | | /* We ensured the common fields structure is shared with all 4 types */ |
5229 | 0 | Dwg_Entity_POLYLINE_2D *_obj = obj->tio.entity->tio.POLYLINE_2D; |
5230 | 0 | Dwg_Data *dwg = obj->parent; |
5231 | |
|
5232 | 0 | if (dwg->header.version >= R_2004) |
5233 | 0 | { |
5234 | 0 | BITCODE_BL i = 0; |
5235 | 0 | Dwg_Object_Ref *layer = obj->tio.entity->layer; |
5236 | 0 | Dwg_Object_Ref *seqend = _obj->seqend; |
5237 | | |
5238 | | // resolve prev. object |
5239 | 0 | if (layer && !layer->obj) |
5240 | 0 | layer->obj = dwg_ref_object_relative (dwg, layer, obj); |
5241 | 0 | if (!layer || !layer->obj) |
5242 | 0 | { // maybe a reactor pointing forwards or vertex |
5243 | 0 | LOG_WARN ("Wrong POLYLINE.layer " FORMAT_HV "", |
5244 | 0 | layer ? layer->handleref.value : 0L); |
5245 | 0 | if (_obj->num_owned > 0 && _obj->vertex) |
5246 | 0 | { |
5247 | 0 | Dwg_Object_Ref *vertex = _obj->vertex[0]; |
5248 | 0 | if (vertex && !vertex->obj) |
5249 | 0 | vertex->obj = dwg_ref_object_relative (dwg, vertex, obj); |
5250 | 0 | if (vertex && vertex->obj /* pointing backwards */ |
5251 | 0 | && vertex->obj->fixedtype == DWG_TYPE_LAYER) |
5252 | 0 | { |
5253 | 0 | Dwg_Object *seq; |
5254 | 0 | obj->tio.entity->layer = layer = vertex; |
5255 | 0 | LOG_WARN ("POLYLINE.layer is vertex[0] " FORMAT_HV |
5256 | 0 | ", shift em, NULL seqend", |
5257 | 0 | layer->handleref.value); |
5258 | | /* shift vertices one back */ |
5259 | 0 | for (i = 0; i < _obj->num_owned - 1; i++) |
5260 | 0 | { |
5261 | 0 | _obj->vertex[i] = _obj->vertex[i + 1]; |
5262 | 0 | } |
5263 | 0 | _obj->vertex[_obj->num_owned - 1] = seqend; |
5264 | 0 | _obj->seqend = NULL; |
5265 | | /* now just seqend is empty. |
5266 | | either 1+ last_vertex, or one before the first. |
5267 | | Here the next object might not be read yet. */ |
5268 | 0 | seq = dwg_next_object (obj); |
5269 | 0 | if (seq && seq->type == DWG_TYPE_SEQEND) |
5270 | 0 | { |
5271 | 0 | LOG_WARN ("POLYLINE.seqend = POLYLINE+1 " FORMAT_HV "", |
5272 | 0 | seq->handle.value); |
5273 | 0 | seqend = _obj->seqend = dwg_find_objectref (dwg, seq); |
5274 | 0 | } |
5275 | 0 | else |
5276 | 0 | { |
5277 | 0 | seq = seqend ? dwg_next_object (seqend->obj) : NULL; |
5278 | 0 | if (seq && seq->type == DWG_TYPE_SEQEND) |
5279 | 0 | { |
5280 | 0 | LOG_WARN ("POLYLINE.seqend = VERTEX+1 " FORMAT_HV "", |
5281 | 0 | seq->handle.value); |
5282 | 0 | seqend = _obj->seqend |
5283 | 0 | = dwg_find_objectref (dwg, seq); |
5284 | 0 | } |
5285 | 0 | } |
5286 | 0 | } |
5287 | 0 | } |
5288 | 0 | } |
5289 | 0 | else if (layer->obj->fixedtype != DWG_TYPE_LAYER |
5290 | 0 | && layer->obj->fixedtype != DWG_TYPE_DICTIONARY) |
5291 | 0 | { // a vertex would be after, a reactor before |
5292 | 0 | LOG_WARN ("Wrong POLYLINE.layer %s", layer->obj->dxfname); |
5293 | 0 | } |
5294 | | // a SEQEND is always after the polyline, so it cannot be resolved yet |
5295 | 0 | if (!seqend || !seqend->handleref.value) |
5296 | 0 | { |
5297 | 0 | LOG_WARN ("Empty POLYLINE.seqend"); |
5298 | 0 | } |
5299 | 0 | else if (seqend->obj && seqend->obj->fixedtype != DWG_TYPE_SEQEND) |
5300 | 0 | { // most likely a vertex, off by one |
5301 | 0 | LOG_WARN ("Wrong POLYLINE.seqend %s", seqend->obj->dxfname); |
5302 | 0 | } |
5303 | 0 | if (!_obj->vertex) |
5304 | 0 | return; |
5305 | 0 | for (; i < _obj->num_owned; i++) |
5306 | 0 | { |
5307 | 0 | Dwg_Object_Ref *v = _obj->vertex[i]; |
5308 | 0 | if (!v || !v->handleref.value) |
5309 | 0 | { |
5310 | 0 | LOG_WARN ("Empty POLYLINE.vertex[%d]", i); |
5311 | 0 | } |
5312 | 0 | else if (v->obj && v->obj->fixedtype != DWG_TYPE_VERTEX_2D |
5313 | 0 | && v->obj->fixedtype != DWG_TYPE_VERTEX_3D |
5314 | 0 | && v->obj->fixedtype != DWG_TYPE_VERTEX_MESH |
5315 | 0 | && v->obj->fixedtype != DWG_TYPE_VERTEX_PFACE |
5316 | 0 | && v->obj->fixedtype != DWG_TYPE_VERTEX_PFACE_FACE) |
5317 | 0 | { |
5318 | 0 | LOG_WARN ("Wrong POLYLINE.vertex[%d] " FORMAT_HV " %s", i, |
5319 | 0 | v->handleref.value, v->obj->dxfname); |
5320 | 0 | } |
5321 | 0 | } |
5322 | 0 | } |
5323 | 0 | } |
5324 | | |
5325 | | /** dwg_decode_variable_type |
5326 | | * decode object by class name, not type. if type > 500. |
5327 | | * returns 0 on success |
5328 | | */ |
5329 | | static int |
5330 | | dwg_decode_variable_type (Dwg_Data *restrict dwg, Bit_Chain *dat, |
5331 | | Bit_Chain *hdl_dat, Dwg_Object *restrict obj) |
5332 | 1.63M | { |
5333 | 1.63M | Dwg_Class *klass; |
5334 | 1.63M | int i; |
5335 | 1.63M | int is_entity; |
5336 | | |
5337 | 1.63M | if (!dwg || !obj || !dat) |
5338 | 0 | return DWG_ERR_INTERNALERROR; |
5339 | 1.63M | i = obj->type - 500; |
5340 | 1.63M | if (i < 0 || i >= dwg->num_classes) |
5341 | 1.63M | { |
5342 | 1.63M | LOG_ERROR ("Invalid object type %d, only %u classes", obj->type, |
5343 | 1.63M | dwg->num_classes); |
5344 | 1.63M | dwg->num_objects--; |
5345 | 1.63M | return DWG_ERR_UNHANDLEDCLASS; |
5346 | 1.63M | } |
5347 | | |
5348 | 1.51k | klass = &dwg->dwg_class[i]; |
5349 | 1.51k | if (!dwg->dwg_class || !klass->dxfname) |
5350 | 558 | { |
5351 | 558 | LOG_ERROR ("Invalid class %d", obj->type); |
5352 | 558 | return DWG_ERR_UNHANDLEDCLASS; |
5353 | 558 | } |
5354 | 953 | obj->dxfname = klass->dxfname; |
5355 | 953 | is_entity = dwg_class_is_entity (klass); |
5356 | | |
5357 | | // clang-format off |
5358 | | // global class dispatcher |
5359 | 953 | #include "classes.inc" |
5360 | | // clang-format on |
5361 | | |
5362 | 953 | LOG_WARN ("Unknown Class %s %d %s (0x%x%s)", is_entity ? "entity" : "object", |
5363 | 953 | klass->number, klass->dxfname, klass->proxyflag, |
5364 | 953 | klass->is_zombie ? "is_zombie" : ""); |
5365 | | |
5366 | 953 | return DWG_ERR_UNHANDLEDCLASS; |
5367 | 1.00M | } |
5368 | | |
5369 | | /** Adds a new empty obj to the dwg->object[] array. |
5370 | | The new object is at &dwg->object[dwg->num_objects-1]. |
5371 | | |
5372 | | Returns 0 or some error codes on success. |
5373 | | Returns -1 if the dwg->object pool was re-alloced, i.e. pointers within |
5374 | | are invalidated. |
5375 | | Returns DWG_ERR_OUTOFMEM otherwise. |
5376 | | */ |
5377 | | EXPORT int |
5378 | | dwg_add_object (Dwg_Data *restrict dwg) |
5379 | 13.3M | { |
5380 | 13.3M | Dwg_Object *restrict obj; |
5381 | 13.3M | BITCODE_BL num = dwg->num_objects; |
5382 | 13.3M | int realloced = 0; |
5383 | 13.3M | loglevel = dwg->opts & DWG_OPTS_LOGLEVEL; |
5384 | 13.3M | if (num && !dwg->num_alloced_objects) |
5385 | 0 | dwg->num_alloced_objects = num; |
5386 | 13.3M | if (!num && !dwg->object) |
5387 | 23.1k | { |
5388 | 23.1k | dwg->object = (Dwg_Object *)calloc (1024, sizeof (Dwg_Object)); |
5389 | 23.1k | dwg->num_alloced_objects = 1024; |
5390 | 23.1k | dwg->dirty_refs = 0; |
5391 | 23.1k | } |
5392 | 13.3M | else if (num >= dwg->num_alloced_objects) |
5393 | 528 | { |
5394 | 528 | Dwg_Object *restrict old = dwg->object; |
5395 | 528 | BITCODE_BL old_num = dwg->num_alloced_objects; |
5396 | 528 | if (!dwg->num_alloced_objects) |
5397 | 0 | dwg->num_alloced_objects = 1; |
5398 | 1.05k | while (num >= dwg->num_alloced_objects) |
5399 | 528 | dwg->num_alloced_objects *= 2; |
5400 | 528 | dwg->object = (Dwg_Object *)realloc ( |
5401 | 528 | dwg->object, dwg->num_alloced_objects * sizeof (Dwg_Object)); |
5402 | 528 | realloced = old != dwg->object; |
5403 | 528 | if (realloced) |
5404 | 508 | { |
5405 | 508 | dwg->dirty_refs = 1; |
5406 | 508 | memset (&dwg->object[old_num], 0, |
5407 | 508 | (dwg->num_alloced_objects - old_num) * sizeof (Dwg_Object)); |
5408 | 508 | LOG_TRACE ("REALLOC dwg->object vector to %u\n", |
5409 | 508 | dwg->num_alloced_objects); |
5410 | 508 | } |
5411 | 528 | } |
5412 | 13.3M | if (!dwg->object) |
5413 | 0 | return DWG_ERR_OUTOFMEM; |
5414 | | |
5415 | 13.3M | obj = &dwg->object[num]; |
5416 | 13.3M | memset (obj, 0, sizeof (Dwg_Object)); |
5417 | 13.3M | obj->index = num; |
5418 | 13.3M | dwg->num_objects++; |
5419 | 13.3M | obj->parent = dwg; |
5420 | 13.3M | return realloced ? -1 : 0; |
5421 | 13.3M | } |
5422 | | |
5423 | | /** Adds an object to the DWG (i.e. dwg->object[dwg->num_objects]) |
5424 | | Returns 0 or some error codes on success. |
5425 | | Returns -1 if the dwg->object pool was re-alloced. |
5426 | | Returns some DWG_ERR_* otherwise. |
5427 | | */ |
5428 | | int |
5429 | | dwg_decode_add_object (Dwg_Data *restrict dwg, Bit_Chain *dat, |
5430 | | Bit_Chain *hdl_dat, size_t address) |
5431 | 13.2M | { |
5432 | 13.2M | size_t objpos, restartpos; |
5433 | 13.2M | Bit_Chain abs_dat = { 0 }; |
5434 | 13.2M | Dwg_Object *restrict obj; |
5435 | 13.2M | BITCODE_BL num = dwg->num_objects; |
5436 | 13.2M | int error = 0; |
5437 | 13.2M | int realloced = 0; |
5438 | | |
5439 | | /* Keep the previous full chain */ |
5440 | 13.2M | abs_dat = *dat; |
5441 | | |
5442 | | /* Use the indicated address for the object |
5443 | | */ |
5444 | 13.2M | dat->byte = address; |
5445 | 13.2M | dat->bit = 0; |
5446 | | |
5447 | | // DEBUG_HERE; |
5448 | | /* |
5449 | | * Reserve memory space for objects. A realloc violates all internal |
5450 | | * pointers. |
5451 | | */ |
5452 | 13.2M | realloced = dwg_add_object (dwg); |
5453 | 13.2M | if (realloced > 0) // i.e. not realloced, but error |
5454 | 0 | { |
5455 | 0 | *dat = abs_dat; |
5456 | 0 | return realloced; // i.e. DWG_ERR_OUTOFMEM |
5457 | 0 | } |
5458 | 13.2M | obj = &dwg->object[num]; |
5459 | 13.2M | LOG_INFO ("==========================================\n" |
5460 | 13.2M | "Object number: %lu/%lX", |
5461 | 13.2M | (unsigned long)num, (unsigned long)num); |
5462 | | |
5463 | 13.2M | if (dat->byte >= dat->size) |
5464 | 3.97M | { |
5465 | 3.97M | LOG_ERROR ("MS size overflow @%" PRIuSIZE, dat->byte); |
5466 | 3.97M | dwg->num_objects--; |
5467 | 3.97M | *dat = abs_dat; |
5468 | 3.97M | return DWG_ERR_VALUEOUTOFBOUNDS; |
5469 | 3.97M | } |
5470 | | // #ifdef DEBUG |
5471 | | // if ((dat->opts & DWG_OPTS_LOGLEVEL) > 5 && obj->index == 12) |
5472 | | // bit_explore_chain (dat, dat->byte, 16); |
5473 | | // #endif |
5474 | 9.23M | obj->size = bit_read_MS (dat); |
5475 | 9.23M | LOG_INFO (", Size: %d [MS]", obj->size); |
5476 | 9.23M | SINCE (R_2010b) |
5477 | 0 | { |
5478 | | /* This is not counted in the object size */ |
5479 | 0 | obj->handlestream_size = bit_read_UMC (dat); |
5480 | 0 | LOG_INFO (", Hdlsize: " FORMAT_UMC " [UMC] ", obj->handlestream_size); |
5481 | 0 | obj->bitsize = obj->size * 8 - obj->handlestream_size; |
5482 | | // TODO boundscheck |
5483 | 0 | } |
5484 | | |
5485 | 9.23M | objpos = bit_position (dat); // absolute |
5486 | 9.23M | obj->address = dat->byte; |
5487 | | |
5488 | | /* Until here dat is absolute. now restrict it */ |
5489 | 9.23M | bit_reset_chain (dat); |
5490 | 9.23M | if (obj->size > dat->size || dat->size > abs_dat.size |
5491 | 6.33M | || &dat->chain[dat->size] < &dat->chain[0] |
5492 | 6.33M | || &abs_dat.chain[abs_dat.size] < &abs_dat.chain[0] |
5493 | 6.33M | || &dat->chain[dat->size] > &abs_dat.chain[abs_dat.size]) |
5494 | 2.89M | { |
5495 | 2.89M | LOG_TRACE ("\n"); |
5496 | 2.89M | LOG_WARN ("Invalid object size %u > %" PRIuSIZE ". Would overflow", |
5497 | 2.89M | obj->size, dat->size); |
5498 | 2.89M | dwg->num_objects--; |
5499 | 2.89M | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
5500 | | #if 0 |
5501 | | obj->size = dat->size - 1; |
5502 | | #else |
5503 | 2.89M | *dat = abs_dat; |
5504 | 2.89M | return error; |
5505 | 2.89M | #endif |
5506 | 2.89M | } |
5507 | 6.33M | dat->size = obj->size; |
5508 | | |
5509 | 6.33M | SINCE (R_2010b) |
5510 | 0 | { |
5511 | 0 | obj->type = bit_read_BOT (dat); |
5512 | 0 | } |
5513 | 6.33M | else |
5514 | 6.33M | { |
5515 | 6.33M | obj->type = bit_read_BS (dat); |
5516 | 6.33M | } |
5517 | 6.33M | LOG_INFO (", Type: %d [%s]", obj->type, |
5518 | 6.33M | dat->from_version >= R_2010 ? "BOT" : "BS"); |
5519 | 6.33M | LOG_HANDLE (", Address: %" PRIuSIZE, obj->address); |
5520 | 6.33M | LOG_INFO ("\n"); |
5521 | 6.33M | restartpos = bit_position (dat); // relative |
5522 | | |
5523 | | /* Check the type of the object |
5524 | | */ |
5525 | 6.33M | switch (obj->type) |
5526 | 6.33M | { |
5527 | 62.3k | case DWG_TYPE_TEXT: |
5528 | 62.3k | error = dwg_decode_TEXT (dat, obj); |
5529 | 62.3k | break; |
5530 | 18.5k | case DWG_TYPE_ATTRIB: |
5531 | 18.5k | error = dwg_decode_ATTRIB (dat, obj); |
5532 | 18.5k | break; |
5533 | 16.1k | case DWG_TYPE_ATTDEF: |
5534 | 16.1k | error = dwg_decode_ATTDEF (dat, obj); |
5535 | 16.1k | break; |
5536 | 32.8k | case DWG_TYPE_BLOCK: |
5537 | 32.8k | error = dwg_decode_BLOCK (dat, obj); |
5538 | 32.8k | break; |
5539 | 27.0k | case DWG_TYPE_ENDBLK: |
5540 | 27.0k | error = dwg_decode_ENDBLK (dat, obj); |
5541 | 27.0k | break; |
5542 | 1.92k | case DWG_TYPE_SEQEND: |
5543 | 1.92k | error = dwg_decode_SEQEND (dat, obj); |
5544 | 1.92k | if (dat->from_version >= R_13b1 && obj->tio.entity->ownerhandle) |
5545 | 141 | { |
5546 | 141 | Dwg_Object *restrict owner = dwg_resolve_handle ( |
5547 | 141 | dwg, obj->tio.entity->ownerhandle->absolute_ref); |
5548 | 141 | if (!owner) |
5549 | 34 | { |
5550 | 34 | LOG_WARN ("no SEQEND.ownerhandle"); |
5551 | 34 | } |
5552 | 107 | else if (owner->fixedtype == DWG_TYPE_INSERT |
5553 | 106 | || owner->fixedtype == DWG_TYPE_MINSERT) |
5554 | 1 | { |
5555 | | /* SEQEND handle for the owner needed in validate_INSERT */ |
5556 | 1 | hash_set (dwg->object_map, obj->handle.value, (uint64_t)num); |
5557 | 1 | (void)dwg_validate_INSERT (owner); |
5558 | 1 | } |
5559 | 106 | else if (owner->fixedtype == DWG_TYPE_POLYLINE_2D |
5560 | 106 | || owner->fixedtype == DWG_TYPE_POLYLINE_3D |
5561 | 106 | || owner->fixedtype == DWG_TYPE_POLYLINE_PFACE |
5562 | 106 | || owner->fixedtype == DWG_TYPE_POLYLINE_MESH) |
5563 | 0 | { |
5564 | 0 | Dwg_Entity_POLYLINE_2D *restrict _obj |
5565 | 0 | = owner->tio.entity->tio.POLYLINE_2D; |
5566 | 0 | if (!_obj->seqend) |
5567 | | /* SEQEND handle for the owner needed in validate_POLYLINE */ |
5568 | 0 | hash_set (dwg->object_map, obj->handle.value, (uint64_t)num); |
5569 | 0 | (void)dwg_validate_POLYLINE (owner); |
5570 | 0 | } |
5571 | 141 | } |
5572 | 1.92k | break; |
5573 | 17.0k | case DWG_TYPE_INSERT: |
5574 | 17.0k | error = dwg_decode_INSERT (dat, obj); |
5575 | 17.0k | break; |
5576 | 19.3k | case DWG_TYPE_MINSERT: |
5577 | 19.3k | error = dwg_decode_MINSERT (dat, obj); |
5578 | 19.3k | break; |
5579 | 1.31k | case DWG_TYPE_VERTEX_2D: |
5580 | 1.31k | error = dwg_decode_VERTEX_2D (dat, obj); |
5581 | 1.31k | break; |
5582 | 2.53k | case DWG_TYPE_VERTEX_3D: |
5583 | 2.53k | error = dwg_decode_VERTEX_3D (dat, obj); |
5584 | 2.53k | break; |
5585 | 38.1k | case DWG_TYPE_VERTEX_MESH: |
5586 | 38.1k | error = dwg_decode_VERTEX_MESH (dat, obj); |
5587 | 38.1k | break; |
5588 | 30.4k | case DWG_TYPE_VERTEX_PFACE: |
5589 | 30.4k | error = dwg_decode_VERTEX_PFACE (dat, obj); |
5590 | 30.4k | break; |
5591 | 732 | case DWG_TYPE_VERTEX_PFACE_FACE: |
5592 | 732 | error = dwg_decode_VERTEX_PFACE_FACE (dat, obj); |
5593 | 732 | break; |
5594 | 5.23k | case DWG_TYPE_POLYLINE_2D: |
5595 | 5.23k | error = dwg_decode_POLYLINE_2D (dat, obj); |
5596 | 5.23k | if (dat->from_version >= R_2010 && error < DWG_ERR_CRITICAL) |
5597 | 0 | check_POLYLINE_handles (obj); |
5598 | 5.23k | break; |
5599 | 29.1k | case DWG_TYPE_POLYLINE_3D: |
5600 | 29.1k | error = dwg_decode_POLYLINE_3D (dat, obj); |
5601 | 29.1k | if (dat->from_version >= R_2010 && error < DWG_ERR_CRITICAL) |
5602 | 0 | check_POLYLINE_handles (obj); |
5603 | 29.1k | break; |
5604 | 20.6k | case DWG_TYPE_ARC: |
5605 | 20.6k | error = dwg_decode_ARC (dat, obj); |
5606 | 20.6k | break; |
5607 | 6.07k | case DWG_TYPE_CIRCLE: |
5608 | 6.07k | error = dwg_decode_CIRCLE (dat, obj); |
5609 | 6.07k | break; |
5610 | 5.37k | case DWG_TYPE_LINE: |
5611 | 5.37k | error = dwg_decode_LINE (dat, obj); |
5612 | 5.37k | break; |
5613 | 41.6k | case DWG_TYPE_DIMENSION_ORDINATE: |
5614 | 41.6k | error = dwg_decode_DIMENSION_ORDINATE (dat, obj); |
5615 | 41.6k | break; |
5616 | 81.1k | case DWG_TYPE_DIMENSION_LINEAR: |
5617 | 81.1k | error = dwg_decode_DIMENSION_LINEAR (dat, obj); |
5618 | 81.1k | break; |
5619 | 10.3k | case DWG_TYPE_DIMENSION_ALIGNED: |
5620 | 10.3k | error = dwg_decode_DIMENSION_ALIGNED (dat, obj); |
5621 | 10.3k | break; |
5622 | 13.6k | case DWG_TYPE_DIMENSION_ANG3PT: |
5623 | 13.6k | error = dwg_decode_DIMENSION_ANG3PT (dat, obj); |
5624 | 13.6k | break; |
5625 | 20.1k | case DWG_TYPE_DIMENSION_ANG2LN: |
5626 | 20.1k | error = dwg_decode_DIMENSION_ANG2LN (dat, obj); |
5627 | 20.1k | break; |
5628 | 14.9k | case DWG_TYPE_DIMENSION_RADIUS: |
5629 | 14.9k | error = dwg_decode_DIMENSION_RADIUS (dat, obj); |
5630 | 14.9k | break; |
5631 | 4.68k | case DWG_TYPE_DIMENSION_DIAMETER: |
5632 | 4.68k | error = dwg_decode_DIMENSION_DIAMETER (dat, obj); |
5633 | 4.68k | break; |
5634 | 839 | case DWG_TYPE_POINT: |
5635 | 839 | error = dwg_decode_POINT (dat, obj); |
5636 | 839 | break; |
5637 | 11.4k | case DWG_TYPE__3DFACE: |
5638 | 11.4k | error = dwg_decode__3DFACE (dat, obj); |
5639 | 11.4k | break; |
5640 | 12.2k | case DWG_TYPE_POLYLINE_PFACE: |
5641 | 12.2k | error = dwg_decode_POLYLINE_PFACE (dat, obj); |
5642 | 12.2k | if (dat->from_version >= R_2010 && error < DWG_ERR_CRITICAL) |
5643 | 0 | check_POLYLINE_handles (obj); |
5644 | 12.2k | break; |
5645 | 4.04k | case DWG_TYPE_POLYLINE_MESH: |
5646 | 4.04k | error = dwg_decode_POLYLINE_MESH (dat, obj); |
5647 | 4.04k | if (dat->from_version >= R_2010) |
5648 | 0 | check_POLYLINE_handles (obj); |
5649 | 4.04k | break; |
5650 | 3.41k | case DWG_TYPE_SOLID: |
5651 | 3.41k | error = dwg_decode_SOLID (dat, obj); |
5652 | 3.41k | break; |
5653 | 22.2k | case DWG_TYPE_TRACE: |
5654 | 22.2k | error = dwg_decode_TRACE (dat, obj); |
5655 | 22.2k | break; |
5656 | 6.15k | case DWG_TYPE_SHAPE: |
5657 | 6.15k | error = dwg_decode_SHAPE (dat, obj); |
5658 | 6.15k | break; |
5659 | 8.25k | case DWG_TYPE_VIEWPORT: |
5660 | 8.25k | error = dwg_decode_VIEWPORT (dat, obj); |
5661 | 8.25k | break; |
5662 | 3.47k | case DWG_TYPE_ELLIPSE: |
5663 | 3.47k | error = dwg_decode_ELLIPSE (dat, obj); |
5664 | 3.47k | break; |
5665 | 21.9k | case DWG_TYPE_SPLINE: |
5666 | 21.9k | error = dwg_decode_SPLINE (dat, obj); |
5667 | 21.9k | break; |
5668 | 51.2k | case DWG_TYPE_REGION: |
5669 | 51.2k | error = dwg_decode_REGION (dat, obj); |
5670 | 51.2k | break; |
5671 | 11.4k | case DWG_TYPE__3DSOLID: |
5672 | 11.4k | error = dwg_decode__3DSOLID (dat, obj); |
5673 | 11.4k | break; |
5674 | 8.89k | case DWG_TYPE_BODY: |
5675 | 8.89k | error = dwg_decode_BODY (dat, obj); |
5676 | 8.89k | break; |
5677 | 9.85k | case DWG_TYPE_RAY: |
5678 | 9.85k | error = dwg_decode_RAY (dat, obj); |
5679 | 9.85k | break; |
5680 | 4.23k | case DWG_TYPE_XLINE: |
5681 | 4.23k | error = dwg_decode_XLINE (dat, obj); |
5682 | 4.23k | break; |
5683 | 2.25k | case DWG_TYPE_DICTIONARY: |
5684 | 2.25k | error = dwg_decode_DICTIONARY (dat, obj); |
5685 | 2.25k | break; |
5686 | 9.88k | case DWG_TYPE_MTEXT: |
5687 | 9.88k | error = dwg_decode_MTEXT (dat, obj); |
5688 | 9.88k | break; |
5689 | 18.7k | case DWG_TYPE_LEADER: |
5690 | 18.7k | error = dwg_decode_LEADER (dat, obj); |
5691 | 18.7k | break; |
5692 | 845 | case DWG_TYPE_TOLERANCE: |
5693 | 845 | error = dwg_decode_TOLERANCE (dat, obj); |
5694 | 845 | break; |
5695 | 5.07k | case DWG_TYPE_MLINE: |
5696 | 5.07k | error = dwg_decode_MLINE (dat, obj); |
5697 | 5.07k | break; |
5698 | 20.8k | case DWG_TYPE_BLOCK_CONTROL: |
5699 | 20.8k | error = dwg_decode_BLOCK_CONTROL (dat, obj); |
5700 | 20.8k | if (!error && obj->tio.object->tio.BLOCK_CONTROL) |
5701 | 207 | { |
5702 | 207 | if (!dwg->block_control.parent) // only once |
5703 | 95 | dwg->block_control = *obj->tio.object->tio.BLOCK_CONTROL; |
5704 | 112 | else |
5705 | 112 | LOG_WARN ("Second BLOCK_CONTROL object ignored"); |
5706 | 207 | } |
5707 | 20.8k | break; |
5708 | 81.8k | case DWG_TYPE_BLOCK_HEADER: |
5709 | 81.8k | error = dwg_decode_BLOCK_HEADER (dat, obj); |
5710 | | /* |
5711 | | * We cannot cache dwg->*space_block here as dwg->objects might get |
5712 | | * realloc'ed. See dwg_model_space_object() and dwg_paper_space_object() |
5713 | | * instead. |
5714 | | */ |
5715 | 81.8k | break; |
5716 | 2.85k | case DWG_TYPE_LAYER_CONTROL: |
5717 | 2.85k | error = dwg_decode_LAYER_CONTROL (dat, obj); |
5718 | 2.85k | break; |
5719 | 3.40k | case DWG_TYPE_LAYER: |
5720 | 3.40k | error = dwg_decode_LAYER (dat, obj); |
5721 | 3.40k | break; |
5722 | 22.1k | case DWG_TYPE_STYLE_CONTROL: |
5723 | 22.1k | error = dwg_decode_STYLE_CONTROL (dat, obj); |
5724 | 22.1k | break; |
5725 | 15.7k | case DWG_TYPE_STYLE: |
5726 | 15.7k | error = dwg_decode_STYLE (dat, obj); |
5727 | 15.7k | break; |
5728 | 9.36k | case DWG_TYPE_LTYPE_CONTROL: |
5729 | 9.36k | error = dwg_decode_LTYPE_CONTROL (dat, obj); |
5730 | 9.36k | break; |
5731 | 39.5k | case DWG_TYPE_LTYPE: |
5732 | 39.5k | error = dwg_decode_LTYPE (dat, obj); |
5733 | 39.5k | break; |
5734 | 5.96k | case DWG_TYPE_VIEW_CONTROL: |
5735 | 5.96k | error = dwg_decode_VIEW_CONTROL (dat, obj); |
5736 | 5.96k | break; |
5737 | 27.3k | case DWG_TYPE_VIEW: |
5738 | 27.3k | error = dwg_decode_VIEW (dat, obj); |
5739 | 27.3k | break; |
5740 | 2.51k | case DWG_TYPE_UCS_CONTROL: |
5741 | 2.51k | error = dwg_decode_UCS_CONTROL (dat, obj); |
5742 | 2.51k | break; |
5743 | 7.81k | case DWG_TYPE_UCS: |
5744 | 7.81k | error = dwg_decode_UCS (dat, obj); |
5745 | 7.81k | break; |
5746 | 31.4k | case DWG_TYPE_VPORT_CONTROL: |
5747 | 31.4k | error = dwg_decode_VPORT_CONTROL (dat, obj); |
5748 | 31.4k | break; |
5749 | 177k | case DWG_TYPE_VPORT: |
5750 | 177k | error = dwg_decode_VPORT (dat, obj); |
5751 | 177k | break; |
5752 | 3.89k | case DWG_TYPE_APPID_CONTROL: |
5753 | 3.89k | error = dwg_decode_APPID_CONTROL (dat, obj); |
5754 | 3.89k | break; |
5755 | 1.81k | case DWG_TYPE_APPID: |
5756 | 1.81k | error = dwg_decode_APPID (dat, obj); |
5757 | 1.81k | break; |
5758 | 13.6k | case DWG_TYPE_DIMSTYLE_CONTROL: |
5759 | 13.6k | error = dwg_decode_DIMSTYLE_CONTROL (dat, obj); |
5760 | 13.6k | break; |
5761 | 26.2k | case DWG_TYPE_DIMSTYLE: |
5762 | 26.2k | error = dwg_decode_DIMSTYLE (dat, obj); |
5763 | 26.2k | break; |
5764 | 1.45k | case DWG_TYPE_VX_CONTROL: |
5765 | 1.45k | error = dwg_decode_VX_CONTROL (dat, obj); |
5766 | 1.45k | break; |
5767 | 2.35k | case DWG_TYPE_VX_TABLE_RECORD: |
5768 | 2.35k | error = dwg_decode_VX_TABLE_RECORD (dat, obj); |
5769 | 2.35k | break; |
5770 | 17.1k | case DWG_TYPE_GROUP: |
5771 | 17.1k | error = dwg_decode_GROUP (dat, obj); |
5772 | 17.1k | break; |
5773 | 29.1k | case DWG_TYPE_MLINESTYLE: |
5774 | 29.1k | error = dwg_decode_MLINESTYLE (dat, obj); |
5775 | 29.1k | break; |
5776 | 1.82k | case DWG_TYPE_OLE2FRAME: |
5777 | 1.82k | error = dwg_decode_OLE2FRAME (dat, obj); |
5778 | 1.82k | break; |
5779 | 1.21k | case DWG_TYPE_DUMMY: |
5780 | 1.21k | error = dwg_decode_DUMMY (dat, obj); |
5781 | 1.21k | break; |
5782 | 11.8k | case DWG_TYPE_LONG_TRANSACTION: |
5783 | 11.8k | error = dwg_decode_LONG_TRANSACTION (dat, obj); |
5784 | 11.8k | break; |
5785 | 36.1k | case DWG_TYPE_LWPOLYLINE: |
5786 | 36.1k | error = dwg_decode_LWPOLYLINE (dat, obj); |
5787 | 36.1k | break; |
5788 | 8.78k | case DWG_TYPE_HATCH: |
5789 | 8.78k | error = dwg_decode_HATCH (dat, obj); |
5790 | 8.78k | break; |
5791 | 5.61k | case DWG_TYPE_XRECORD: |
5792 | 5.61k | error = dwg_decode_XRECORD (dat, obj); |
5793 | 5.61k | break; |
5794 | 12.4k | case DWG_TYPE_PLACEHOLDER: |
5795 | 12.4k | error = dwg_decode_PLACEHOLDER (dat, obj); |
5796 | 12.4k | break; |
5797 | 638 | case DWG_TYPE_OLEFRAME: |
5798 | 638 | error = dwg_decode_OLEFRAME (dat, obj); |
5799 | 638 | break; |
5800 | 20.5k | case DWG_TYPE_VBA_PROJECT: |
5801 | | // LOG_ERROR ("Unhandled Object VBA_PROJECT. Has its own section"); |
5802 | 20.5k | error = dwg_decode_VBA_PROJECT (dat, obj); |
5803 | | // error = DWG_ERR_UNHANDLEDCLASS; |
5804 | 20.5k | break; |
5805 | 895 | case DWG_TYPE_LAYOUT: |
5806 | 895 | error = dwg_decode_LAYOUT (dat, obj); |
5807 | 895 | break; |
5808 | 732 | case DWG_TYPE_PROXY_ENTITY: |
5809 | 732 | error = dwg_decode_PROXY_ENTITY (dat, obj); |
5810 | 732 | break; |
5811 | 270 | case DWG_TYPE_PROXY_OBJECT: |
5812 | 270 | error = dwg_decode_PROXY_OBJECT (dat, obj); |
5813 | 270 | break; |
5814 | 4.95M | default: |
5815 | 4.95M | if (obj->type == dwg->layout_type) |
5816 | 3.32M | error = dwg_decode_LAYOUT (dat, obj); |
5817 | | /* > 500 */ |
5818 | 1.63M | else if ((error = dwg_decode_variable_type (dwg, dat, hdl_dat, obj)) |
5819 | 1.63M | & DWG_ERR_UNHANDLEDCLASS) |
5820 | 1.63M | { |
5821 | 1.63M | int is_entity = 0; |
5822 | 1.63M | int i = obj->type - 500; |
5823 | 1.63M | Dwg_Class *klass = NULL; |
5824 | | |
5825 | | /* restart and read into the UNKNOWN_OBJ object */ |
5826 | | /* the relative offset from type after common_entity_data */ |
5827 | | // obj->common_size = bit_position(dat) - restartpos; |
5828 | | // LOG_HANDLE("common_size: %" PRIuSIZE "\n", obj->common_size); // |
5829 | | // needed for unknown |
5830 | 1.63M | bit_set_position (dat, restartpos); |
5831 | | |
5832 | 1.63M | if (i >= 0 && i < (int)dwg->num_classes) |
5833 | 1.51k | { |
5834 | 1.51k | klass = &dwg->dwg_class[i]; |
5835 | 1.51k | is_entity = dwg_class_is_entity (klass); |
5836 | 1.51k | } |
5837 | 1.63M | else |
5838 | 1.63M | { |
5839 | 1.63M | if (i < 0) |
5840 | 397k | LOG_ERROR ("Invalid class index %d < 0", i); |
5841 | 1.23M | else |
5842 | 1.23M | LOG_ERROR ("Invalid class index %d >= %d", i, |
5843 | 1.63M | (int)dwg->num_classes); |
5844 | 1.63M | obj->type = 0; |
5845 | 1.63M | *dat = abs_dat; |
5846 | 1.63M | return error | DWG_ERR_VALUEOUTOFBOUNDS; |
5847 | 1.63M | } |
5848 | | |
5849 | | // properly dwg_decode_object/_entity for eed, reactors, xdic |
5850 | 1.51k | if (is_entity) |
5851 | 0 | { |
5852 | | // obj->type = DWG_TYPE_UNKNOWN_ENT; |
5853 | 0 | error |= dwg_decode_UNKNOWN_ENT (dat, obj); |
5854 | 0 | } |
5855 | 1.51k | else |
5856 | 1.51k | { |
5857 | | // obj->type = DWG_TYPE_UNKNOWN_OBJ; |
5858 | 1.51k | error |= dwg_decode_UNKNOWN_OBJ (dat, obj); |
5859 | 1.51k | } |
5860 | | |
5861 | 1.51k | if (error >= DWG_ERR_CRITICAL) |
5862 | 0 | *dat = abs_dat; |
5863 | 1.51k | } |
5864 | 6.33M | } |
5865 | | |
5866 | 4.70M | if (obj->handle.value) |
5867 | 862k | { // empty only with UNKNOWN |
5868 | 862k | LOG_HANDLE (" object_map{" FORMAT_HV "} = %lu\n", obj->handle.value, |
5869 | 862k | (unsigned long)num); |
5870 | 862k | hash_set (dwg->object_map, obj->handle.value, (uint64_t)num); |
5871 | 862k | } |
5872 | | |
5873 | 4.70M | if (dat->byte > 8 * dat->size) |
5874 | 0 | { |
5875 | 0 | LOG_ERROR ("Invalid object address (overflow): %" PRIuSIZE |
5876 | 0 | " > %" PRIuSIZE, |
5877 | 0 | dat->byte, 8 * dat->size); |
5878 | 0 | *dat = abs_dat; |
5879 | 0 | return error | DWG_ERR_INVALIDDWG; |
5880 | 0 | } |
5881 | | |
5882 | | /* Restore the old absolute chain. |
5883 | | CRC needs to be calculated from address, which is before our 0 position. |
5884 | | */ |
5885 | 4.70M | restartpos = bit_position (dat); |
5886 | 4.70M | *dat = abs_dat; |
5887 | 4.70M | bit_set_position (dat, objpos + restartpos); |
5888 | 4.70M | if (dat->byte >= dat->size) |
5889 | 3.13k | { |
5890 | 3.13k | LOG_ERROR ("Invalid object position (overflow): %" PRIuSIZE |
5891 | 3.13k | " > %" PRIuSIZE, |
5892 | 3.13k | dat->byte, dat->size); |
5893 | 3.13k | *dat = abs_dat; |
5894 | 3.13k | return error | DWG_ERR_INVALIDDWG; |
5895 | 3.13k | } |
5896 | | |
5897 | | /* Now 1 padding bits until next byte, and then a RS CRC */ |
5898 | 4.70M | if (dat->bit) |
5899 | 1.85M | { |
5900 | 1.85M | unsigned char r = 8 - dat->bit; |
5901 | 1.85M | LOG_HANDLE (" padding: %X/%X (%d bits)\n", dat->chain[dat->byte], |
5902 | 1.85M | dat->chain[dat->byte] & ((1 << r) - 1), r); |
5903 | 1.85M | bit_advance_position (dat, r); |
5904 | 1.85M | } |
5905 | 4.70M | bit_set_position (dat, (obj->address + obj->size) * 8 - 2); |
5906 | 4.70M | if (!bit_check_CRC (dat, address, 0xC0C1)) |
5907 | 4.70M | error |= DWG_ERR_WRONGCRC; |
5908 | | |
5909 | | /* Reset to previous addresses for return */ |
5910 | 4.70M | *dat = abs_dat; |
5911 | | |
5912 | 4.70M | return realloced ? -1 : error; // re-alloced or not |
5913 | 4.70M | } |
5914 | | |
5915 | | /** dwg_decode_unknown |
5916 | | Container to hold a unknown class entity, see classes.inc |
5917 | | Every DEBUGGING class holds a bits array, a bitsize, and the handle |
5918 | | and string stream offsets. |
5919 | | It starts after the common_entity|object_data until and goes until the end |
5920 | | of final padding, to the CRC. |
5921 | | (obj->common_size/8 .. obj->size) |
5922 | | */ |
5923 | | int |
5924 | | dwg_decode_unknown_bits (Bit_Chain *restrict dat, Dwg_Object *restrict obj) |
5925 | 13.2k | { |
5926 | | // bitsize does not include the handles size |
5927 | 13.2k | int num_bytes; |
5928 | 13.2k | size_t pos = bit_position (dat); |
5929 | 13.2k | long num_bits = ((8 * obj->size) - pos) & ULONG_MAX; |
5930 | 13.2k | if (num_bits < 0) |
5931 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
5932 | | |
5933 | 13.2k | obj->num_unknown_bits = (BITCODE_RL)num_bits; |
5934 | 13.2k | num_bytes = num_bits / 8; |
5935 | 13.2k | if (num_bits % 8) |
5936 | 11.9k | num_bytes++; |
5937 | | |
5938 | 13.2k | obj->unknown_bits = bit_read_bits (dat, num_bits); |
5939 | 13.2k | if (!obj->unknown_bits) |
5940 | 0 | { |
5941 | 0 | bit_set_position (dat, pos); |
5942 | 0 | obj->num_unknown_bits = 0; |
5943 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
5944 | 0 | } |
5945 | | // [num_bits (commonsize, hdlpos, strsize) num_bytes TF] |
5946 | 13.2k | LOG_TRACE ("unknown_bits [%ld (%" PRIuSIZE ",%ld,%d) %d TF]: ", num_bits, |
5947 | 13.2k | obj->common_size, (long)(obj->bitsize - obj->common_size), |
5948 | 13.2k | (int)obj->stringstream_size, num_bytes); |
5949 | 13.2k | LOG_TRACE_TF (obj->unknown_bits, num_bytes); |
5950 | 13.2k | LOG_TRACE ("\n"); |
5951 | 13.2k | bit_set_position (dat, pos); |
5952 | 13.2k | return 0; |
5953 | 13.2k | } |
5954 | | |
5955 | | int |
5956 | | dwg_decode_unknown_rest (Bit_Chain *restrict dat, Dwg_Object *restrict obj) |
5957 | 0 | { |
5958 | | // check in which object stream we are: common, object, text or handles? |
5959 | | // for now we only need the text |
5960 | | |
5961 | | // bitsize does not include the handles size |
5962 | 0 | int num_bytes; |
5963 | 0 | size_t pos = bit_position (dat); |
5964 | 0 | long num_bits; |
5965 | 0 | if (pos < obj->bitsize) // data or text |
5966 | 0 | num_bits = (obj->bitsize - pos) & ULONG_MAX; |
5967 | 0 | else // or handles |
5968 | 0 | num_bits = ((8 * obj->size) - pos) & ULONG_MAX; |
5969 | 0 | if (num_bits < 0) |
5970 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
5971 | | |
5972 | 0 | obj->num_unknown_rest = (BITCODE_RL)num_bits; |
5973 | 0 | num_bytes = num_bits / 8; |
5974 | 0 | if (num_bits % 8) |
5975 | 0 | num_bytes++; |
5976 | |
|
5977 | 0 | obj->unknown_rest = bit_read_bits (dat, num_bits); |
5978 | 0 | if (!obj->unknown_rest) |
5979 | 0 | { |
5980 | 0 | bit_set_position (dat, pos); |
5981 | 0 | obj->num_unknown_rest = 0; |
5982 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
5983 | 0 | } |
5984 | | // [num_bits (commonsize, hdlpos, strsize) num_bytes TF] |
5985 | 0 | LOG_TRACE ("unknown_rest [%ld (%" PRIuSIZE ",%ld,%d) %d TF]: ", num_bits, |
5986 | 0 | obj->common_size, (long)(obj->bitsize - obj->common_size), |
5987 | 0 | (int)obj->stringstream_size, num_bytes); |
5988 | 0 | LOG_TRACE_TF (obj->unknown_rest, num_bytes); |
5989 | 0 | LOG_TRACE ("\n"); |
5990 | 0 | bit_set_position (dat, pos); |
5991 | 0 | return 0; |
5992 | 0 | } |
5993 | | |
5994 | | /* We need the full block name, not from BLOCK_HEADER, but the BLOCK entity. |
5995 | | unicode is allocated as utf-8. |
5996 | | */ |
5997 | | char * |
5998 | | dwg_dim_blockname (Dwg_Data *restrict dwg, const Dwg_Object *restrict obj) |
5999 | 59.9k | { |
6000 | 59.9k | BITCODE_H block = NULL; |
6001 | 59.9k | if (dwg_dynapi_entity_value (obj->tio.entity->tio.DIMENSION_LINEAR, |
6002 | 59.9k | obj->name, "block", &block, NULL)) |
6003 | 59.9k | { |
6004 | 59.9k | return block ? dwg_handle_name (dwg, "BLOCK", block) : NULL; |
6005 | 59.9k | } |
6006 | 0 | return NULL; |
6007 | 59.9k | } |
6008 | | |
6009 | | /* Ensure that the given refs have rising objid's/indices (when read in natural |
6010 | | * order). With mips32 -O2 inline would fail. |
6011 | | */ |
6012 | | static int |
6013 | | ref_after (const Dwg_Object_Ref *restrict r1, |
6014 | | const Dwg_Object_Ref *restrict r2) |
6015 | 0 | { |
6016 | 0 | if (!r1 || !r2 || !r1->obj || !r2->obj) |
6017 | 0 | return 0; |
6018 | 0 | return r1->obj->index >= r2->obj->index ? 1 : 0; |
6019 | 0 | } |
6020 | | |
6021 | | /* just look at the next object, if it's a SEQEND (i.e ENDBLK) */ |
6022 | | int |
6023 | | dwg_validate_INSERT (Dwg_Object *restrict obj) |
6024 | 1 | { |
6025 | 1 | Dwg_Object *restrict next = dwg_next_object (obj); |
6026 | | |
6027 | 1 | if (obj->fixedtype == DWG_TYPE_INSERT) |
6028 | 1 | { |
6029 | 1 | Dwg_Entity_INSERT *restrict _obj = obj->tio.entity->tio.INSERT; |
6030 | 1 | Dwg_Object_Ref *restrict seqend = _obj->seqend; |
6031 | 1 | if (!_obj->has_attribs) |
6032 | 0 | return 1; |
6033 | 1 | if (!seqend || next == seqend->obj) |
6034 | 0 | { |
6035 | 0 | LOG_TRACE ("unsorted INSERT " FORMAT_HV " SEQEND " FORMAT_RLLx |
6036 | 0 | " ATTRIB\n", |
6037 | 0 | obj->handle.value, |
6038 | 0 | seqend && seqend->obj ? seqend->obj->handle.value : 0L); |
6039 | 0 | return 0; |
6040 | 0 | } |
6041 | 1 | } |
6042 | 0 | else if (obj->fixedtype == DWG_TYPE_MINSERT) |
6043 | 0 | { |
6044 | 0 | Dwg_Entity_MINSERT *restrict _obj = obj->tio.entity->tio.MINSERT; |
6045 | 0 | Dwg_Object_Ref *restrict seqend = _obj->seqend; |
6046 | 0 | if (!_obj->has_attribs) |
6047 | 0 | return 1; |
6048 | 0 | if (!seqend || next == seqend->obj) |
6049 | 0 | { |
6050 | 0 | LOG_TRACE ("unsorted INSERT " FORMAT_HV " SEQEND " FORMAT_RLLx |
6051 | 0 | " ATTRIB\n", |
6052 | 0 | obj->handle.value, |
6053 | 0 | seqend && seqend->obj ? seqend->obj->handle.value : 0L); |
6054 | 0 | return 0; |
6055 | 0 | } |
6056 | 0 | } |
6057 | 1 | return 1; |
6058 | 1 | } |
6059 | | |
6060 | | int |
6061 | | dwg_validate_POLYLINE (Dwg_Object *restrict obj) |
6062 | 0 | { |
6063 | | /* We ensured the common fields structure is shared with all 4 types */ |
6064 | 0 | Dwg_Entity_POLYLINE_2D *restrict _obj = obj->tio.entity->tio.POLYLINE_2D; |
6065 | 0 | Dwg_Data *restrict dwg = obj->parent; |
6066 | |
|
6067 | 0 | if (dwg->header.version > R_11) |
6068 | 0 | { |
6069 | 0 | Dwg_Object_Ref *restrict seqend = _obj->seqend; |
6070 | | /* if shifted in check_POLYLINE_handles() seqend might be empty */ |
6071 | 0 | if (!seqend) |
6072 | 0 | { /* either the first or last */ |
6073 | 0 | Dwg_Object *restrict next = dwg_next_object (obj); |
6074 | 0 | if (next && next->fixedtype == DWG_TYPE_SEQEND) |
6075 | 0 | { |
6076 | 0 | seqend = dwg_find_objectref ( |
6077 | 0 | dwg, next); // usually not found, even with set hash |
6078 | 0 | if (seqend == NULL) |
6079 | 0 | { |
6080 | 0 | seqend |
6081 | 0 | = (Dwg_Object_Ref *)calloc (1, sizeof (Dwg_Object_Ref)); |
6082 | 0 | seqend->obj = next; |
6083 | 0 | seqend->handleref = next->handle; |
6084 | 0 | seqend->absolute_ref = next->handle.value; |
6085 | 0 | dwg_decode_add_object_ref (dwg, seqend); |
6086 | 0 | } |
6087 | 0 | _obj->seqend = seqend; |
6088 | 0 | LOG_WARN ("fixed empty POLYLINE.seqend with +1 obj"); |
6089 | 0 | } |
6090 | 0 | else if (_obj->vertex) |
6091 | 0 | { |
6092 | 0 | Dwg_Object_Ref *restrict ref = _obj->vertex[_obj->num_owned - 1]; |
6093 | 0 | if (ref && ref->obj) |
6094 | 0 | { |
6095 | 0 | next = dwg_next_object (ref->obj); |
6096 | 0 | if (next && next->fixedtype == DWG_TYPE_SEQEND) |
6097 | 0 | { |
6098 | 0 | seqend = dwg_find_objectref (dwg, next); |
6099 | 0 | if (seqend == NULL) |
6100 | 0 | { |
6101 | 0 | seqend = (Dwg_Object_Ref *)calloc ( |
6102 | 0 | 1, sizeof (Dwg_Object_Ref)); |
6103 | 0 | seqend->obj = next; |
6104 | 0 | seqend->handleref = next->handle; |
6105 | 0 | seqend->absolute_ref = next->handle.value; |
6106 | 0 | dwg_decode_add_object_ref (dwg, seqend); |
6107 | 0 | } |
6108 | 0 | _obj->seqend = seqend; |
6109 | 0 | LOG_WARN ( |
6110 | 0 | "fixed empty POLYLINE.seqend with last vertex +1"); |
6111 | 0 | } |
6112 | 0 | } |
6113 | 0 | } |
6114 | 0 | } |
6115 | 0 | } |
6116 | 0 | if (dwg->header.version > R_11 && dwg->header.version <= R_2000) |
6117 | 0 | { |
6118 | 0 | Dwg_Object_Ref *restrict first_vertex = _obj->first_vertex; |
6119 | 0 | Dwg_Object_Ref *restrict last_vertex = _obj->last_vertex; |
6120 | 0 | Dwg_Object_Ref *restrict seqend = _obj->seqend; |
6121 | 0 | if (ref_after (first_vertex, last_vertex) |
6122 | 0 | || ref_after (last_vertex, seqend)) |
6123 | 0 | { |
6124 | 0 | LOG_TRACE ("unsorted POLYLINE VERTEX SEQEND\n"); |
6125 | 0 | return 0; |
6126 | 0 | } |
6127 | 0 | } |
6128 | 0 | else if (dwg->header.version >= R_2004 && _obj->vertex) |
6129 | 0 | { |
6130 | 0 | BITCODE_BL i = 1; |
6131 | 0 | Dwg_Object_Ref *restrict first_vertex = _obj->vertex[0]; |
6132 | 0 | Dwg_Object_Ref *restrict seqend = _obj->seqend; |
6133 | 0 | if (ref_after (first_vertex, seqend)) |
6134 | 0 | { |
6135 | | /* r2010+ often mix up the hdlstream offset: |
6136 | | layer,vertex*,seqend. check the types then also */ |
6137 | 0 | if (first_vertex->obj->index < obj->index) |
6138 | 0 | { |
6139 | 0 | LOG_WARN ("skip wrong POLYLINE.vertex[0] handle " FORMAT_HV |
6140 | 0 | " < " FORMAT_HV "\n", |
6141 | 0 | first_vertex->obj->handle.value, obj->handle.value); |
6142 | 0 | if (_obj->num_owned > 1) |
6143 | 0 | first_vertex = _obj->vertex[1]; |
6144 | 0 | i = 2; |
6145 | 0 | } |
6146 | 0 | else |
6147 | 0 | { |
6148 | 0 | LOG_TRACE ("unsorted POLYLINE VERTEX SEQEND\n"); |
6149 | 0 | return 0; |
6150 | 0 | } |
6151 | 0 | } |
6152 | 0 | for (; i < _obj->num_owned; i++) |
6153 | 0 | { |
6154 | 0 | if (ref_after (first_vertex, _obj->vertex[i]) |
6155 | 0 | || ref_after (_obj->vertex[i], seqend)) |
6156 | 0 | { |
6157 | 0 | LOG_TRACE ("unsorted POLYLINE VERTEX SEQEND\n"); |
6158 | 0 | return 0; |
6159 | 0 | } |
6160 | 0 | } |
6161 | 0 | } |
6162 | 0 | return 1; |
6163 | 0 | } |
6164 | | |
6165 | | /* Creates a handleref for an entity link (prev/next/first/last entity), |
6166 | | checking for cycles by traversing from first via next_entity. |
6167 | | Returns NULL if adding handle_val would create a cycle. |
6168 | | Used from importers (in_dxf.c, in_json.c) where ->obj pointers are valid. |
6169 | | Not used in the decode path itself, since refs are resolved post-decode. */ |
6170 | | Dwg_Object_Ref * |
6171 | | dwg_add_entity_link (Dwg_Data *restrict dwg, const Dwg_Object *restrict first, |
6172 | | const char *restrict field, const BITCODE_RLL handle_val) |
6173 | 1.93k | { |
6174 | 1.93k | loglevel = dwg->opts & DWG_OPTS_LOGLEVEL; |
6175 | 1.93k | if (!handle_val) |
6176 | 0 | return dwg_add_handleref (dwg, 4, 0, NULL); |
6177 | | /* Check for cycles: traverse from first via next_entity */ |
6178 | 1.93k | if (first) |
6179 | 0 | { |
6180 | 0 | const Dwg_Object *obj = first; |
6181 | 0 | BITCODE_BL steps = 0; |
6182 | 0 | const BITCODE_BL max_steps = dwg->num_objects; |
6183 | 0 | while (obj && steps++ < max_steps) |
6184 | 0 | { |
6185 | 0 | if (obj->handle.value == handle_val) |
6186 | 0 | { |
6187 | 0 | LOG_WARN ("Cycle in entity link %s: handle " FORMAT_RLLx |
6188 | 0 | " already in chain\n", |
6189 | 0 | field, handle_val); |
6190 | 0 | return NULL; |
6191 | 0 | } |
6192 | 0 | if (obj->supertype != DWG_SUPERTYPE_ENTITY || !obj->tio.entity) |
6193 | 0 | break; |
6194 | 0 | { |
6195 | 0 | const Dwg_Object_Ref *next = obj->tio.entity->next_entity; |
6196 | 0 | if (!next || !next->absolute_ref || !next->obj) |
6197 | 0 | break; |
6198 | 0 | obj = next->obj; |
6199 | 0 | } |
6200 | 0 | } |
6201 | 0 | } |
6202 | 1.93k | return dwg_add_handleref (dwg, 4, handle_val, NULL); |
6203 | 1.93k | } |
6204 | | |
6205 | | /* Validate r13-r2000 entity link chains for cycles, using a visited bitset. |
6206 | | Called after resolve_objectref_vector in decode_R13_R2000. |
6207 | | Clears cyclic next_entity links when detected. */ |
6208 | | static int |
6209 | | dwg_validate_entity_links (Dwg_Data *restrict dwg) |
6210 | 1.62k | { |
6211 | 1.62k | int changes = 0; |
6212 | 1.62k | loglevel = dwg->opts & DWG_OPTS_LOGLEVEL; |
6213 | 1.62k | if (dwg->header.version > R_2000 || dwg->header.version < R_13b1) |
6214 | 143 | return 0; |
6215 | 1.47k | LOG_TRACE ("\ndwg_validate_entity_links:\n"); |
6216 | 275k | for (BITCODE_BL i = 0; i < dwg->num_objects; i++) |
6217 | 274k | { |
6218 | 274k | Dwg_Object *hdr_obj = &dwg->object[i]; |
6219 | 274k | if (hdr_obj->fixedtype == DWG_TYPE_BLOCK_HEADER && hdr_obj->tio.object |
6220 | 6.05k | && hdr_obj->tio.object->tio.BLOCK_HEADER) |
6221 | 6.05k | { |
6222 | 6.05k | Dwg_Object_BLOCK_HEADER *_hdr |
6223 | 6.05k | = hdr_obj->tio.object->tio.BLOCK_HEADER; |
6224 | 6.05k | Dwg_Object *cur, *prev; |
6225 | 6.05k | BITCODE_BL steps = 0; |
6226 | 6.05k | const BITCODE_BL max_steps = dwg->num_objects; |
6227 | 6.05k | uint8_t *visited; |
6228 | 6.05k | size_t visited_size; |
6229 | | |
6230 | 6.05k | if (!_hdr || !_hdr->first_entity || !_hdr->first_entity->obj) |
6231 | 5.68k | continue; |
6232 | | |
6233 | 368 | visited_size = ((size_t)max_steps + 7) / 8; |
6234 | 368 | visited = calloc (visited_size, 1); |
6235 | 368 | if (!visited) |
6236 | 0 | continue; |
6237 | | |
6238 | 368 | prev = NULL; |
6239 | 368 | cur = _hdr->first_entity->obj; |
6240 | 368 | while (cur && steps < max_steps) |
6241 | 368 | { |
6242 | 368 | Dwg_Object_Entity *ent; |
6243 | 368 | BITCODE_BL idx = cur->index; |
6244 | | |
6245 | 368 | if (idx >= max_steps) |
6246 | 0 | { |
6247 | 0 | if (prev && prev->tio.entity) |
6248 | 0 | prev->tio.entity->next_entity = NULL; |
6249 | 0 | changes++; |
6250 | 0 | break; |
6251 | 0 | } |
6252 | 368 | if ((visited[idx / 8] >> (idx % 8)) & 1) |
6253 | 0 | { |
6254 | 0 | LOG_WARN ( |
6255 | 0 | "Cycle in entity links for BLOCK_HEADER " FORMAT_RLLx |
6256 | 0 | ": entity " FORMAT_RLLx " already visited, clearing\n", |
6257 | 0 | hdr_obj->handle.value, cur->handle.value); |
6258 | 0 | if (prev && prev->tio.entity) |
6259 | 0 | prev->tio.entity->next_entity = NULL; |
6260 | 0 | changes++; |
6261 | 0 | break; |
6262 | 0 | } |
6263 | 368 | visited[idx / 8] |= (uint8_t)(1 << (idx % 8)); |
6264 | | |
6265 | 368 | ent = cur->tio.entity; |
6266 | 368 | if (cur->supertype != DWG_SUPERTYPE_ENTITY || !ent |
6267 | 265 | || !ent->next_entity || !ent->next_entity->obj) |
6268 | 368 | break; |
6269 | 0 | prev = cur; |
6270 | 0 | cur = ent->next_entity->obj; |
6271 | 0 | steps++; |
6272 | 0 | } |
6273 | | |
6274 | 368 | free (visited); |
6275 | 368 | } |
6276 | 274k | } |
6277 | 1.47k | LOG_TRACE ("\n"); |
6278 | 1.47k | return changes; |
6279 | 1.62k | } |
6280 | | |
6281 | | /* Set prev_ and next_entity handles from all block headers. |
6282 | | Needed after decode or import from r2004+ to r13-r2000. */ |
6283 | | int |
6284 | | dwg_fixup_BLOCKS_entities (Dwg_Data *restrict dwg) |
6285 | 3.21k | { |
6286 | 3.21k | int changes = 0; |
6287 | 3.21k | int is_uni = 0; |
6288 | | // also run for DXF imports (INDXF and ADD only, not INJSON), since |
6289 | | // in_postprocess_handles uses array index adjacency, not handle adjacency, |
6290 | | // to set nolinks. dwg_add_Document sets DWG_OPTS_IN = INDXF|INJSON for |
6291 | | // API-created documents; real DXF imports set only INDXF. Exclude the |
6292 | | // API-created case (INJSON set) to avoid clobbering first_entity before |
6293 | | // entities have been added. |
6294 | 3.21k | if (dwg->header.version > R_2000 |
6295 | 3.21k | || (dwg->header.from_version <= R_2000 |
6296 | 3.20k | && (!(dwg->opts & DWG_OPTS_INDXF) || (dwg->opts & DWG_OPTS_INJSON)))) |
6297 | 2.80k | return 0; |
6298 | 411 | is_uni = dwg->header.version >= R_2007; |
6299 | 411 | loglevel = dwg->opts & DWG_OPTS_LOGLEVEL; |
6300 | 411 | LOG_TRACE ("\ndwg_fixup_BLOCKS_entities:\n"); |
6301 | 14.3k | for (BITCODE_BL i = 0; i < dwg->num_objects; i++) |
6302 | 13.9k | { |
6303 | 13.9k | Dwg_Object *obj = &dwg->object[i]; |
6304 | 13.9k | if (obj->fixedtype == DWG_TYPE_BLOCK_HEADER) |
6305 | 3.73k | { |
6306 | 3.73k | Dwg_Object_BLOCK_HEADER *_obj = obj->tio.object->tio.BLOCK_HEADER; |
6307 | 3.73k | char *_objname; |
6308 | 3.73k | if (!_obj) |
6309 | 0 | continue; |
6310 | 3.73k | _objname |
6311 | 3.73k | = is_uni ? bit_convert_TU ((BITCODE_TU)_obj->name) : _obj->name; |
6312 | 3.73k | LOG_TRACE ("BLOCK_HEADER %s: %u\n", _objname, |
6313 | 3.73k | (unsigned)_obj->num_owned); |
6314 | 3.73k | if (!_obj->entities) |
6315 | 3.65k | { |
6316 | 3.65k | _obj->first_entity = dwg_add_handleref (dwg, 4, 0, NULL); |
6317 | 3.65k | _obj->last_entity = dwg_add_handleref (dwg, 4, 0, NULL); |
6318 | 3.65k | if (_obj->num_owned) |
6319 | 0 | LOG_ERROR ("BLOCK_HEADER %s: %u => 0 num_owned\n", _objname, |
6320 | 3.65k | (unsigned)_obj->num_owned); |
6321 | 3.65k | _obj->num_owned = 0; |
6322 | 3.65k | } |
6323 | | // link from first_entity to last_entity |
6324 | 5.13k | for (BITCODE_BL j = 0; j < _obj->num_owned; j++) |
6325 | 1.39k | { |
6326 | 1.39k | Dwg_Object_Ref *hdl = _obj->entities[j]; |
6327 | 1.39k | Dwg_Object_Ref *prev = j > 0 ? _obj->entities[j - 1] : NULL; |
6328 | 1.39k | Dwg_Object_Ref *next |
6329 | 1.39k | = j + 1 < _obj->num_owned ? _obj->entities[j + 1] : NULL; |
6330 | 1.39k | BITCODE_RLL prev_ref = prev ? prev->absolute_ref : 0; |
6331 | 1.39k | BITCODE_RLL next_ref = next ? next->absolute_ref : 0; |
6332 | 1.39k | BITCODE_RLL cur_ref = 0; |
6333 | 1.39k | Dwg_Object *o = NULL; |
6334 | 1.39k | Dwg_Object_Entity *ent = NULL; |
6335 | | |
6336 | 1.39k | if (!hdl) |
6337 | 0 | continue; |
6338 | 1.39k | cur_ref = hdl->absolute_ref; |
6339 | 1.39k | LOG_HANDLE ("entities[%u]: " FORMAT_REF " \n", j, |
6340 | 1.39k | ARGS_REF (hdl)); |
6341 | 1.39k | o = dwg_ref_object (dwg, hdl); // may fail! |
6342 | 1.39k | ent = o ? o->tio.entity : NULL; |
6343 | 1.39k | if (!o) |
6344 | 0 | continue; |
6345 | 1.39k | if (o->supertype != DWG_SUPERTYPE_ENTITY) |
6346 | 1 | { |
6347 | 1 | LOG_ERROR ("Illegal BLOCK_HEADER %s.entities[%u] %s", |
6348 | 1 | _objname, j, o->name); |
6349 | 1 | changes++; |
6350 | 1 | if (is_uni) |
6351 | 0 | free (_objname); |
6352 | 1 | continue; |
6353 | 1 | } |
6354 | | // only log changes |
6355 | 1.39k | if (prev_ref == 0L && next_ref == 0L) |
6356 | 1 | { |
6357 | 1 | if (!ent->nolinks) |
6358 | 0 | { |
6359 | 0 | LOG_TRACE ("nolinks: 1\n"); |
6360 | 0 | ent->nolinks = 1; |
6361 | 0 | changes++; |
6362 | 0 | } |
6363 | 1 | } |
6364 | 1.39k | else if (prev_ref && prev_ref == cur_ref - 1 && next_ref |
6365 | 1.08k | && next_ref == cur_ref + 1) |
6366 | 1.07k | { |
6367 | 1.07k | if (!ent->nolinks) |
6368 | 270 | { |
6369 | 270 | LOG_TRACE ("nolinks: 1\n"); |
6370 | 270 | ent->nolinks = 1; |
6371 | 270 | changes++; |
6372 | 270 | } |
6373 | 1.07k | } |
6374 | 320 | else if (prev_ref && next_ref && ent->nolinks) |
6375 | 153 | { |
6376 | 153 | LOG_TRACE ("nolinks: 0\n"); |
6377 | 153 | ent->nolinks = 0; |
6378 | 153 | changes++; |
6379 | 153 | } |
6380 | 1.39k | if (j == 0) // first: prev_entity must be NULL |
6381 | 80 | { |
6382 | 80 | if (!_obj->first_entity) |
6383 | 0 | { |
6384 | 0 | LOG_TRACE ("first_entity: " FORMAT_HV "\n", |
6385 | 0 | hdl->absolute_ref); |
6386 | 0 | _obj->first_entity |
6387 | 0 | = dwg_add_handleref (dwg, 4, hdl->absolute_ref, o); |
6388 | 0 | } |
6389 | 80 | else if (_obj->first_entity->absolute_ref |
6390 | 80 | != hdl->absolute_ref) |
6391 | 0 | { |
6392 | 0 | LOG_WARN ("Fixup wrong BLOCK_HEADER %s.first_entity " |
6393 | 0 | "from " FORMAT_HV " to " FORMAT_RLLx, |
6394 | 0 | _objname, _obj->first_entity->absolute_ref, |
6395 | 0 | hdl->absolute_ref); |
6396 | 0 | changes++; |
6397 | 0 | _obj->first_entity |
6398 | 0 | = dwg_add_handleref (dwg, 4, hdl->absolute_ref, o); |
6399 | 0 | } |
6400 | 80 | } |
6401 | 1.39k | if (ent->prev_entity == NULL) |
6402 | 1.39k | { |
6403 | 1.39k | if (!prev_ref) |
6404 | 80 | { |
6405 | 80 | LOG_TRACE ("nolinks: 0\n"); |
6406 | 80 | ent->nolinks = 0; |
6407 | 80 | } |
6408 | 1.39k | LOG_TRACE (" " FORMAT_HV ": prev_entity " FORMAT_RLLx ", ", |
6409 | 1.39k | hdl->absolute_ref, prev_ref); |
6410 | 1.39k | ent->prev_entity = dwg_add_handleref (dwg, 4, prev_ref, o); |
6411 | 1.39k | } |
6412 | 4 | else if (ent->prev_entity->absolute_ref != prev_ref) |
6413 | 4 | { |
6414 | 4 | LOG_WARN ("Fixup wrong BLOCK_HEADER " |
6415 | 4 | "%s.entities[%d].prev_entity from " FORMAT_HV |
6416 | 4 | " to " FORMAT_HV, |
6417 | 4 | _objname, j, ent->prev_entity->absolute_ref, |
6418 | 4 | prev_ref); |
6419 | 4 | changes++; |
6420 | 4 | ent->prev_entity = dwg_add_handleref (dwg, 4, prev_ref, o); |
6421 | 4 | } |
6422 | 1.39k | if (ent->next_entity == NULL) |
6423 | 1.39k | { |
6424 | 1.39k | LOG_TRACE (" next_entity " FORMAT_HV "\n", next_ref); |
6425 | 1.39k | ent->next_entity = dwg_add_handleref (dwg, 4, next_ref, o); |
6426 | 1.39k | if (!next_ref) |
6427 | 79 | { |
6428 | 79 | LOG_TRACE (" nolinks: 0\n"); |
6429 | 79 | ent->nolinks = 0; |
6430 | 79 | } |
6431 | 1.39k | } |
6432 | 4 | else if (ent->next_entity->absolute_ref != next_ref) |
6433 | 4 | { |
6434 | 4 | LOG_WARN ("Fixup wrong BLOCK_HEADER " |
6435 | 4 | "%s.entities[%d].next_entity from " FORMAT_HV |
6436 | 4 | " to " FORMAT_HV, |
6437 | 4 | _objname, j, ent->next_entity->absolute_ref, |
6438 | 4 | next_ref); |
6439 | 4 | changes++; |
6440 | 4 | ent->next_entity = dwg_add_handleref (dwg, 4, next_ref, o); |
6441 | 4 | } |
6442 | 1.39k | if (j == _obj->num_owned - 1) // last: next_entity must be NULL |
6443 | 81 | { |
6444 | 81 | if (!_obj->last_entity) |
6445 | 0 | { |
6446 | 0 | LOG_TRACE ("last_entity: " FORMAT_HV "\n", |
6447 | 0 | hdl->absolute_ref); |
6448 | 0 | _obj->last_entity |
6449 | 0 | = dwg_add_handleref (dwg, 4, hdl->absolute_ref, o); |
6450 | 0 | } |
6451 | 81 | else if (_obj->last_entity->absolute_ref |
6452 | 81 | != hdl->absolute_ref) |
6453 | 0 | { |
6454 | 0 | LOG_WARN ("Fixup wrong BLOCK_HEADER %s.last_entity " |
6455 | 0 | "from " FORMAT_HV " to " FORMAT_RLLx, |
6456 | 0 | _objname, _obj->last_entity->absolute_ref, |
6457 | 0 | hdl->absolute_ref); |
6458 | 0 | changes++; |
6459 | 0 | _obj->last_entity |
6460 | 0 | = dwg_add_handleref (dwg, 4, hdl->absolute_ref, o); |
6461 | 0 | } |
6462 | 81 | } |
6463 | 1.39k | } |
6464 | 3.73k | if (is_uni) |
6465 | 0 | free (_objname); |
6466 | 3.73k | } |
6467 | 13.9k | } |
6468 | | // DXF roundtrip may leave VERTEX/SEQEND children of block polylines |
6469 | | // with entmode=2 (model space). Fix them up by scanning backwards |
6470 | | // for the POLYLINE/INSERT owner and inheriting its entmode. |
6471 | 14.3k | for (BITCODE_BL i = 0; i < dwg->num_objects; i++) |
6472 | 13.9k | { |
6473 | 13.9k | Dwg_Object *obj = &dwg->object[i]; |
6474 | 13.9k | if (obj->supertype != DWG_SUPERTYPE_ENTITY || !obj->tio.entity) |
6475 | 6.02k | continue; |
6476 | 7.90k | if (obj->tio.entity->entmode != 2) |
6477 | 6.28k | continue; |
6478 | 1.62k | if (obj->fixedtype != DWG_TYPE_VERTEX_2D |
6479 | 1.62k | && obj->fixedtype != DWG_TYPE_VERTEX_3D |
6480 | 1.62k | && obj->fixedtype != DWG_TYPE_VERTEX_MESH |
6481 | 1.62k | && obj->fixedtype != DWG_TYPE_VERTEX_PFACE |
6482 | 1.62k | && obj->fixedtype != DWG_TYPE_VERTEX_PFACE_FACE |
6483 | 1.62k | && obj->fixedtype != DWG_TYPE_SEQEND) |
6484 | 1.10k | continue; |
6485 | | // Scan backwards for the POLYLINE/INSERT owner |
6486 | 7.96k | for (BITCODE_BL j = i; j > 0; j--) |
6487 | 7.66k | { |
6488 | 7.66k | Dwg_Object *owner = &dwg->object[j - 1]; |
6489 | 7.66k | if (owner->fixedtype == DWG_TYPE_INSERT |
6490 | 7.66k | || owner->fixedtype == DWG_TYPE_MINSERT |
6491 | 7.66k | || owner->fixedtype == DWG_TYPE_POLYLINE_2D |
6492 | 7.44k | || owner->fixedtype == DWG_TYPE_POLYLINE_3D |
6493 | 7.44k | || owner->fixedtype == DWG_TYPE_POLYLINE_PFACE |
6494 | 7.44k | || owner->fixedtype == DWG_TYPE_POLYLINE_MESH) |
6495 | 220 | { |
6496 | 220 | if (owner->tio.entity->entmode == 3) |
6497 | 0 | { |
6498 | 0 | obj->tio.entity->entmode = 3; |
6499 | 0 | LOG_TRACE ("Fixup %s.entmode -> 3 (owner %s)\n", obj->name, |
6500 | 0 | owner->name); |
6501 | 0 | changes++; |
6502 | 0 | } |
6503 | 220 | break; |
6504 | 220 | } |
6505 | 7.66k | } |
6506 | 514 | } |
6507 | 411 | dwg_validate_entity_links (dwg); |
6508 | 411 | LOG_TRACE ("\n"); |
6509 | 411 | return changes; |
6510 | 3.21k | } |
6511 | | |
6512 | | // for DXF |
6513 | | // length 38 |
6514 | | void |
6515 | | dxf_3dsolid_revisionguid (Dwg_Entity_3DSOLID *_obj) |
6516 | 0 | { |
6517 | 0 | sprintf ((char *)_obj->revision_guid, |
6518 | 0 | "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", |
6519 | 0 | (unsigned long)_obj->revision_major, |
6520 | 0 | (unsigned)_obj->revision_minor1, (unsigned)_obj->revision_minor2, |
6521 | 0 | _obj->revision_bytes[0], _obj->revision_bytes[1], |
6522 | 0 | _obj->revision_bytes[2], _obj->revision_bytes[3], |
6523 | 0 | _obj->revision_bytes[4], _obj->revision_bytes[5], |
6524 | 0 | _obj->revision_bytes[6], _obj->revision_bytes[7]); |
6525 | 0 | LOG_TRACE ("revision_guid: %s\n", (char *)_obj->revision_guid); |
6526 | 0 | } |
6527 | | |
6528 | | int |
6529 | | decode_preR13_DIMENSION (Bit_Chain *restrict dat, Dwg_Object *restrict obj) |
6530 | 201k | { |
6531 | 201k | int error = dwg_setup_DIMENSION_ANG2LN (obj); |
6532 | 201k | Dwg_Object_Entity *_ent = obj->tio.entity; |
6533 | 201k | Bit_Chain *hdl_dat = dat; |
6534 | 201k | Dwg_Data *dwg = obj->parent; |
6535 | 201k | BITCODE_RC dimtype = 0; |
6536 | 201k | { |
6537 | | // decode a generic DIMENSION, and fixup the type after. DIMENSION_ANG2LN |
6538 | | // is the biggest. |
6539 | 201k | Dwg_Entity_DIMENSION_ANG2LN *_obj; |
6540 | 201k | Bit_Chain *str_dat = dat; |
6541 | 201k | LOG_INFO ("Decode entity DIMENSION\n"); |
6542 | 201k | _obj = _ent->tio.DIMENSION_ANG2LN; |
6543 | 201k | error |= decode_entity_preR13 (dat, obj, _ent); |
6544 | 1.03M | COMMON_ENTITY_DIMENSION |
6545 | 1.03M | dimtype = _obj->flag; |
6546 | 1.03M | } |
6547 | | |
6548 | 0 | switch (dimtype & 15) |
6549 | 1.03M | { |
6550 | 44.0k | case FLAG_R11_DIMENSION_LINEAR: |
6551 | 44.0k | { |
6552 | 44.0k | Dwg_Entity_DIMENSION_LINEAR *_obj = _ent->tio.DIMENSION_LINEAR; |
6553 | 44.0k | obj->fixedtype = DWG_TYPE_DIMENSION_LINEAR; |
6554 | 44.0k | LOG_TRACE ("=> Entity DIMENSION_LINEAR\n"); |
6555 | 44.0k | if (R11OPTS (8)) |
6556 | 20.7k | { |
6557 | 20.7k | if (dat->version >= R_10) |
6558 | 14.1k | FIELD_3RD (xline1_pt, 13) |
6559 | 6.60k | else |
6560 | 6.60k | FIELD_2RD (xline1_pt, 13) |
6561 | 20.7k | } |
6562 | 40.4k | if (R11OPTS (16)) |
6563 | 20.2k | { |
6564 | 20.2k | if (dat->version >= R_10) |
6565 | 14.1k | FIELD_3RD (xline2_pt, 14) |
6566 | 6.07k | else |
6567 | 6.07k | FIELD_2RD (xline2_pt, 14) |
6568 | 20.2k | } |
6569 | 38.0k | if (R11OPTS (0x100)) |
6570 | 38.0k | FIELD_RD0 (dim_rotation, 50); |
6571 | 37.2k | if (R11OPTS (0x200)) |
6572 | 37.2k | FIELD_RD0 (oblique_angle, 52); // ext_line_rotation |
6573 | 36.5k | if (R11OPTS (0x400)) |
6574 | 36.5k | FIELD_RD0 (text_rotation, 53); |
6575 | 35.1k | if (R11OPTS (0x4000)) |
6576 | 32.1k | FIELD_3RD (extrusion, 210); |
6577 | 32.1k | if (R11OPTS (0x8000)) |
6578 | 32.1k | FIELD_HANDLE (dimstyle, 2, 0); |
6579 | 32.1k | } |
6580 | 0 | break; |
6581 | 7.40k | case FLAG_R11_DIMENSION_ALIGNED: |
6582 | 7.40k | { |
6583 | 7.40k | Dwg_Entity_DIMENSION_ALIGNED *_obj = _ent->tio.DIMENSION_ALIGNED; |
6584 | 7.40k | obj->fixedtype = DWG_TYPE_DIMENSION_ALIGNED; |
6585 | 7.40k | LOG_TRACE ("=> Entity DIMENSION_ALIGNED\n"); |
6586 | 7.40k | if (R11OPTS (8)) |
6587 | 6.91k | { |
6588 | 6.91k | if (dat->version >= R_10) |
6589 | 2.75k | FIELD_3RD (xline1_pt, 13) |
6590 | 4.16k | else |
6591 | 4.16k | FIELD_2RD (xline1_pt, 13) |
6592 | 6.91k | } |
6593 | 6.51k | if (R11OPTS (16)) |
6594 | 6.23k | { |
6595 | 6.23k | if (dat->version >= R_10) |
6596 | 2.73k | FIELD_3RD (xline2_pt, 14) |
6597 | 3.50k | else |
6598 | 3.50k | FIELD_2RD (xline2_pt, 14) |
6599 | 6.23k | } |
6600 | 4.04k | if (R11OPTS (0x100)) |
6601 | 3.86k | FIELD_RD (oblique_angle, 50); |
6602 | 3.86k | if (R11OPTS (0x400)) |
6603 | 3.86k | FIELD_RD0 (text_rotation, 53); |
6604 | 3.64k | if (R11OPTS (0x8000)) |
6605 | 3.64k | FIELD_HANDLE (dimstyle, 2, 0); |
6606 | 3.64k | } |
6607 | 0 | break; |
6608 | 24.2k | case FLAG_R11_DIMENSION_ANG2LN: |
6609 | 24.2k | { |
6610 | 24.2k | Dwg_Entity_DIMENSION_ANG2LN *_obj = _ent->tio.DIMENSION_ANG2LN; |
6611 | 24.2k | obj->fixedtype = DWG_TYPE_DIMENSION_ANG2LN; |
6612 | 24.2k | if (R11OPTS (8)) |
6613 | 22.3k | { |
6614 | 22.3k | if (dat->version >= R_10) |
6615 | 12.9k | FIELD_3RD (xline1start_pt, 13) |
6616 | 9.36k | else |
6617 | 9.36k | FIELD_2RD (xline1start_pt, 13) |
6618 | 22.3k | } |
6619 | 19.5k | if (R11OPTS (16)) |
6620 | 15.6k | { |
6621 | 15.6k | if (dat->version >= R_10) |
6622 | 8.88k | FIELD_3RD (xline1end_pt, 14) |
6623 | 6.81k | else |
6624 | 6.81k | FIELD_2RD (xline1end_pt, 14) |
6625 | 15.6k | } |
6626 | 16.0k | if (R11OPTS (32)) |
6627 | 12.6k | { |
6628 | 12.6k | if (dat->version >= R_10) |
6629 | 6.50k | FIELD_3RD (xline2start_pt, 15) |
6630 | 6.13k | else |
6631 | 6.13k | FIELD_2RD (xline2start_pt, 15) |
6632 | 12.6k | } |
6633 | 11.9k | if (R11OPTS (64)) |
6634 | 10.6k | FIELD_2RD (xline2end_pt, 16); |
6635 | 8.60k | if (R11OPTS (0x400)) |
6636 | 8.60k | FIELD_RD0 (text_rotation, 53); |
6637 | 7.81k | if (R11OPTS (0x8000)) |
6638 | 7.81k | FIELD_HANDLE (dimstyle, 2, 0); |
6639 | 7.81k | } |
6640 | 0 | break; |
6641 | 11.2k | case FLAG_R11_DIMENSION_DIAMETER: |
6642 | 11.2k | { |
6643 | 11.2k | Dwg_Entity_DIMENSION_DIAMETER *_obj = _ent->tio.DIMENSION_DIAMETER; |
6644 | 11.2k | obj->fixedtype = DWG_TYPE_DIMENSION_DIAMETER; |
6645 | 11.2k | LOG_TRACE ("=> Entity DIMENSION_DIAMETER\n"); |
6646 | 11.2k | if (R11OPTS (32)) |
6647 | 11.0k | { |
6648 | 11.0k | if (dat->version >= R_10 && !R11FLAG (FLAG_R11_HAS_ELEVATION)) |
6649 | 104 | FIELD_3RD (first_arc_pt, 15) |
6650 | 10.9k | else |
6651 | 10.9k | FIELD_2RD (first_arc_pt, 15) |
6652 | 11.0k | } |
6653 | 9.00k | if (R11OPTS (128)) |
6654 | 8.70k | FIELD_RD (leader_len, 40); |
6655 | 8.24k | if (R11OPTS (0x400)) |
6656 | 8.24k | FIELD_RD0 (text_rotation, 53); |
6657 | 7.70k | if (R11OPTS (0x4000)) |
6658 | 6.42k | FIELD_3RD (extrusion, 210); |
6659 | 6.42k | if (R11OPTS (0x8000)) |
6660 | 6.42k | FIELD_HANDLE (dimstyle, 2, 0); |
6661 | 6.42k | } |
6662 | 0 | break; |
6663 | 11.9k | case FLAG_R11_DIMENSION_RADIUS: |
6664 | 11.9k | { |
6665 | 11.9k | Dwg_Entity_DIMENSION_RADIUS *_obj = _ent->tio.DIMENSION_RADIUS; |
6666 | 11.9k | obj->fixedtype = DWG_TYPE_DIMENSION_RADIUS; |
6667 | 11.9k | LOG_TRACE ("=> Entity DIMENSION_RADIUS\n"); |
6668 | 11.9k | if (R11OPTS (32)) |
6669 | 8.38k | { |
6670 | 8.38k | if (dat->version >= R_10) |
6671 | 1.43k | FIELD_3RD (first_arc_pt, 15) |
6672 | 6.94k | else |
6673 | 6.94k | FIELD_2RD (first_arc_pt, 15) |
6674 | 8.38k | } |
6675 | 9.86k | if (R11OPTS (128)) |
6676 | 9.67k | FIELD_RD (leader_len, 40); |
6677 | 9.67k | if (R11OPTS (0x400)) |
6678 | 9.67k | FIELD_RD0 (text_rotation, 53); |
6679 | 9.16k | if (R11OPTS (0x4000)) |
6680 | 8.49k | FIELD_3RD (extrusion, 210); |
6681 | 8.49k | if (R11OPTS (0x8000)) |
6682 | 8.49k | FIELD_HANDLE (dimstyle, 2, 0); |
6683 | 8.49k | } |
6684 | 0 | break; |
6685 | 13.4k | case FLAG_R11_DIMENSION_ANG3PT: |
6686 | 13.4k | { |
6687 | 13.4k | Dwg_Entity_DIMENSION_ANG3PT *_obj = _ent->tio.DIMENSION_ANG3PT; |
6688 | 13.4k | obj->fixedtype = DWG_TYPE_DIMENSION_ANG3PT; |
6689 | 13.4k | LOG_TRACE ("=> Entity DIMENSION_ANG3PT\n"); |
6690 | 13.4k | if (R11OPTS (8)) |
6691 | 12.5k | { |
6692 | 12.5k | if (dat->version >= R_10) |
6693 | 5.47k | FIELD_3RD (xline1_pt, 13) |
6694 | 7.12k | else |
6695 | 7.12k | FIELD_2RD (xline1_pt, 13) |
6696 | 12.5k | } |
6697 | 11.9k | if (R11OPTS (16)) |
6698 | 11.4k | { |
6699 | 11.4k | if (dat->version >= R_10) |
6700 | 4.99k | FIELD_3RD (xline2_pt, 14) |
6701 | 6.45k | else |
6702 | 6.45k | FIELD_2RD (xline2_pt, 14) |
6703 | 11.4k | } |
6704 | 10.1k | if (R11OPTS (32)) |
6705 | 9.51k | { |
6706 | 9.51k | if (dat->version >= R_10) |
6707 | 4.47k | FIELD_3RD (center_pt, 15) |
6708 | 5.03k | else |
6709 | 5.03k | FIELD_2RD (center_pt, 15) |
6710 | 9.51k | } |
6711 | 8.09k | if (R11OPTS (64)) |
6712 | 6.91k | FIELD_2RD (xline2end_pt, 0) |
6713 | 6.32k | if (R11OPTS (0x400)) |
6714 | 6.32k | FIELD_RD0 (text_rotation, 53); |
6715 | 6.02k | if (R11OPTS (0x8000)) |
6716 | 6.02k | FIELD_HANDLE (dimstyle, 2, 0); |
6717 | 6.02k | } |
6718 | 0 | break; |
6719 | 13.4k | case FLAG_R11_DIMENSION_ORDINATE: |
6720 | 13.4k | { |
6721 | 13.4k | Dwg_Entity_DIMENSION_ORDINATE *_obj = _ent->tio.DIMENSION_ORDINATE; |
6722 | 13.4k | obj->fixedtype = DWG_TYPE_DIMENSION_ORDINATE; |
6723 | 13.4k | LOG_TRACE ("=> Entity DIMENSION_ORDINATE\n"); |
6724 | 13.4k | if (R11OPTS (8)) |
6725 | 6.64k | { // if dxf 13 (extension_defining_pt) |
6726 | 6.64k | if (dat->version >= R_10) |
6727 | 3.45k | FIELD_3RD (feature_location_pt, 13) |
6728 | 3.18k | else |
6729 | 3.18k | FIELD_2RD (feature_location_pt, 13) |
6730 | 6.64k | } |
6731 | 13.2k | if (R11OPTS (16)) |
6732 | 12.4k | { // extension_defining_point2 |
6733 | 12.4k | if (dat->version >= R_10) |
6734 | 5.03k | FIELD_3RD (leader_endpt, 14) |
6735 | 7.38k | else |
6736 | 7.38k | FIELD_2RD (leader_endpt, 14) |
6737 | 12.4k | } |
6738 | 11.0k | if (R11OPTS (0x400)) |
6739 | 11.0k | FIELD_RD0 (text_rotation, 53); |
6740 | 10.9k | if (R11OPTS (0x8000)) |
6741 | 10.9k | FIELD_HANDLE (dimstyle, 2, 0); |
6742 | 10.9k | } |
6743 | 0 | break; |
6744 | 40.0k | default: |
6745 | 40.0k | LOG_ERROR ("Unknown preR13 DIMENSION type %u", dimtype); |
6746 | 40.0k | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
6747 | 1.03M | } |
6748 | | |
6749 | 115k | return error; |
6750 | 1.03M | } |
6751 | | |
6752 | | int |
6753 | | decode_preR13_sentinel (const Dwg_Sentinel sentinel, |
6754 | | const char *restrict sentinel_name, |
6755 | | Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
6756 | 51 | { |
6757 | 51 | int error = 0; |
6758 | 51 | const unsigned char *const wanted = dwg_sentinel (sentinel); |
6759 | 51 | BITCODE_TF r11_sentinel; |
6760 | | |
6761 | 51 | if (dat->byte + 16 > dat->size) |
6762 | 23 | { |
6763 | 23 | LOG_ERROR ("%s buffer overflow at pos %" PRIuSIZE " > size %" PRIuSIZE, |
6764 | 23 | __FUNCTION__, dat->byte + 16, dat->size); |
6765 | 23 | return DWG_ERR_INVALIDDWG; |
6766 | 23 | } |
6767 | 28 | r11_sentinel = bit_read_TF (dat, 16U); |
6768 | 28 | if (!r11_sentinel) |
6769 | 0 | return DWG_ERR_INVALIDDWG; |
6770 | 28 | LOG_TRACE ("%s: ", sentinel_name); |
6771 | 28 | LOG_RPOS; |
6772 | 28 | LOG_TRACE_TF (r11_sentinel, 16); |
6773 | 28 | if (memcmp (r11_sentinel, wanted, 16)) |
6774 | 28 | { |
6775 | | /* Search +- 1000 bytes around, as the comment always said. It was |
6776 | | actually +-200 (pos = byte - 200, len = 400), which misses real files: |
6777 | | a r11 drawing here has every table sentinel displaced from where the |
6778 | | header's table address puts it, LAYER_BEGIN by -300 and VIEW_BEGIN by |
6779 | | -608, so this recovery never fired and the whole file was rejected. */ |
6780 | 28 | const size_t window = 1000; |
6781 | 28 | size_t pos = dat->byte > window ? dat->byte - window : 0; |
6782 | 28 | size_t len = MIN (dat->size - pos, 2 * window); |
6783 | 28 | char *found = (char *)memmem (&dat->chain[pos], len, wanted, 16); |
6784 | 28 | if (!found) |
6785 | 28 | { |
6786 | 28 | LOG_ERROR ("%s not found at %" PRIuSIZE, sentinel_name, |
6787 | 28 | dat->byte - 16); |
6788 | 28 | error = DWG_ERR_SECTIONNOTFOUND; |
6789 | 28 | } |
6790 | 0 | else |
6791 | 0 | { |
6792 | 0 | pos = (ptrdiff_t)found - (ptrdiff_t)&dat->chain[0]; |
6793 | 0 | LOG_WARN ("%s not found at %" PRIuSIZE ", but at %" PRIuSIZE, |
6794 | 0 | sentinel_name, dat->byte - 16, pos); |
6795 | 0 | dat->byte = pos + 16; |
6796 | 0 | error = DWG_ERR_WRONGCRC; |
6797 | 0 | } |
6798 | 28 | } |
6799 | 28 | free (r11_sentinel); |
6800 | | |
6801 | 28 | return error; |
6802 | 28 | } |
6803 | | |
6804 | | static void |
6805 | | decode_preR13_section_chk (Dwg_Section_Type_r11 id, Bit_Chain *restrict dat, |
6806 | | Dwg_Data *restrict dwg) |
6807 | 0 | { |
6808 | 0 | Dwg_Section *tbl = &dwg->header.section[id]; |
6809 | 0 | BITCODE_RS id1, size; |
6810 | 0 | BITCODE_RLL address; |
6811 | 0 | BITCODE_RLd number; |
6812 | |
|
6813 | 0 | #define CMP(f, type) \ |
6814 | 0 | if (tbl->f != f) \ |
6815 | 0 | LOG_ERROR ("decode_preR13_section_chk %s %s", tbl->name, #f); |
6816 | |
|
6817 | 0 | if ((BITCODE_RL)id > dwg->header.num_sections) |
6818 | 0 | { |
6819 | 0 | LOG_ERROR ( |
6820 | 0 | "decode_preR13_section_chk: Invalid table %u, have only " FORMAT_RL, |
6821 | 0 | (unsigned)id, dwg->header.num_sections); |
6822 | 0 | return; |
6823 | 0 | } |
6824 | 0 | id1 = bit_read_RS (dat); |
6825 | 0 | size = bit_read_RS (dat); |
6826 | 0 | CMP (size, RS); |
6827 | 0 | number = (BITCODE_RLd)bit_read_RS (dat); |
6828 | 0 | CMP (number, RLd); |
6829 | 0 | address = (BITCODE_RLL)bit_read_RL (dat); |
6830 | 0 | CMP (address, RLL) |
6831 | 0 | #undef CMP |
6832 | 0 | LOG_TRACE ("chk table %-8s [%2d]: size:%-4u nr:%-3ld (" FORMAT_RLL ")\n", |
6833 | 0 | tbl->name, (int)id1, (unsigned)size, (long)number, address); |
6834 | 0 | } |
6835 | | |
6836 | | #define DECODE_PRER13_SENTINEL(ID) \ |
6837 | 51 | error |= decode_preR13_sentinel (ID, #ID, dat, dwg) |
6838 | | |
6839 | | // only in R11 |
6840 | | int |
6841 | | decode_r11_auxheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) |
6842 | 0 | { |
6843 | 0 | int error = 0; |
6844 | 0 | BITCODE_RS crc, crcc; |
6845 | 0 | Dwg_AuxHeader *_obj = &dwg->auxheader; |
6846 | 0 | size_t pos = dat->byte; |
6847 | |
|
6848 | 0 | LOG_TRACE ("\nAUXHEADER: @0x%zx\n", dat->byte); |
6849 | 0 | DECODE_PRER13_SENTINEL (DWG_SENTINEL_R11_AUXHEADER_BEGIN); |
6850 | 0 | FIELD_RS (num_auxheader_variables, 0); |
6851 | 0 | FIELD_RS (auxheader_size, 0); |
6852 | 0 | FIELD_RLx (entities_start, 0); |
6853 | 0 | if (_obj->entities_start != dwg->header.entities_start) |
6854 | 0 | { |
6855 | 0 | LOG_WARN ("entities_start %x/%x", _obj->entities_start, |
6856 | 0 | dwg->header.entities_start); |
6857 | 0 | } |
6858 | 0 | FIELD_RLx (entities_end, 0); |
6859 | 0 | if (_obj->entities_end != dwg->header.entities_end) |
6860 | 0 | { |
6861 | 0 | LOG_WARN ("entities_end %x/%x", _obj->entities_end, |
6862 | 0 | dwg->header.entities_end); |
6863 | 0 | } |
6864 | 0 | FIELD_RLx (blocks_start, 0); |
6865 | 0 | if (_obj->blocks_start != dwg->header.blocks_start) |
6866 | 0 | { |
6867 | 0 | LOG_WARN ("blocks_start %x/%x", _obj->blocks_start, |
6868 | 0 | dwg->header.blocks_start); |
6869 | 0 | } |
6870 | 0 | FIELD_RLx (extras_start, 0); |
6871 | 0 | if (_obj->extras_start != dwg->header.extras_start) |
6872 | 0 | { |
6873 | 0 | LOG_WARN ("extras_start %x/%x", _obj->extras_start, |
6874 | 0 | dwg->header.extras_start); |
6875 | 0 | } |
6876 | 0 | FIELD_RS (R11_HANDLING, 0); |
6877 | 0 | _obj->HANDSEED = bit_read_RLL_BE (dat); |
6878 | 0 | LOG_TRACE ("HANDSEED: " FORMAT_RLLx " [RLLx 0]\n", _obj->HANDSEED); |
6879 | 0 | FIELD_RS (num_aux_tables, 0); |
6880 | 0 | decode_preR13_section_chk (SECTION_BLOCK, dat, dwg); |
6881 | 0 | decode_preR13_section_chk (SECTION_LAYER, dat, dwg); |
6882 | 0 | decode_preR13_section_chk (SECTION_STYLE, dat, dwg); |
6883 | 0 | decode_preR13_section_chk (SECTION_LTYPE, dat, dwg); |
6884 | 0 | decode_preR13_section_chk (SECTION_VIEW, dat, dwg); |
6885 | 0 | if (dwg->header.num_sections >= SECTION_VPORT) |
6886 | 0 | { |
6887 | 0 | decode_preR13_section_chk (SECTION_UCS, dat, dwg); |
6888 | 0 | decode_preR13_section_chk (SECTION_VPORT, dat, dwg); |
6889 | 0 | } |
6890 | 0 | if (dwg->header.num_sections >= SECTION_APPID) |
6891 | 0 | { |
6892 | 0 | decode_preR13_section_chk (SECTION_APPID, dat, dwg); |
6893 | 0 | } |
6894 | 0 | if (dwg->header.num_sections >= SECTION_VX) |
6895 | 0 | { |
6896 | 0 | decode_preR13_section_chk (SECTION_DIMSTYLE, dat, dwg); |
6897 | 0 | decode_preR13_section_chk (SECTION_VX, dat, dwg); |
6898 | 0 | } |
6899 | 0 | FIELD_RLx (auxheader_address, 0); |
6900 | 0 | if (_obj->auxheader_address < pos |
6901 | | // lower bound |
6902 | 0 | || _obj->auxheader_address > UINT32_MAX - 16 |
6903 | | // upper bound |
6904 | 0 | || _obj->auxheader_address + 16 + _obj->auxheader_size > dat->size) |
6905 | 0 | { |
6906 | 0 | LOG_ERROR ("Invalid auxheader_address %04X or size %u", |
6907 | 0 | _obj->auxheader_address, (unsigned)_obj->auxheader_size); |
6908 | 0 | error |= DWG_ERR_WRONGCRC; |
6909 | 0 | return error; |
6910 | 0 | } |
6911 | 0 | if (_obj->auxheader_address != pos) |
6912 | 0 | { |
6913 | 0 | LOG_WARN ("Invalid auxheader_address %04X", _obj->auxheader_address); |
6914 | 0 | error |= DWG_ERR_WRONGCRC; |
6915 | 0 | } |
6916 | 0 | else if (_obj->auxheader_size < 2) |
6917 | 0 | { |
6918 | 0 | LOG_WARN ("Invalid auxheader_size " FORMAT_RS, _obj->auxheader_size); |
6919 | 0 | error |= DWG_ERR_WRONGCRC; |
6920 | 0 | } |
6921 | 0 | else |
6922 | 0 | { |
6923 | 0 | crcc = bit_calc_CRC (0xC0C1, |
6924 | | // after sentinel (16 bytes) |
6925 | 0 | &dat->chain[_obj->auxheader_address + 16], |
6926 | | // minus crc length (2 bytes) |
6927 | 0 | _obj->auxheader_size - 2); |
6928 | 0 | crc = bit_read_RS (dat); |
6929 | 0 | LOG_TRACE ("crc: %04X [RSx] from 0x%x-0x%zx\n", crc, |
6930 | 0 | _obj->auxheader_address + 16, dat->byte - 2); |
6931 | 0 | if (crc != crcc) |
6932 | 0 | { |
6933 | 0 | LOG_ERROR ("AUX header CRC mismatch %04X <=> %04X", crc, crcc); |
6934 | 0 | error |= DWG_ERR_WRONGCRC; |
6935 | 0 | } |
6936 | 0 | } |
6937 | 0 | DECODE_PRER13_SENTINEL (DWG_SENTINEL_R11_AUXHEADER_END); |
6938 | 0 | LOG_TRACE ("\n"); |
6939 | |
|
6940 | 0 | return error; |
6941 | 0 | } |
6942 | | |
6943 | | // sentinel on begin and end is part of this decoding in case of R11 |
6944 | | // start and end addresses are without sentinel |
6945 | | int |
6946 | | decode_preR13_entities (BITCODE_RL start, BITCODE_RL end, |
6947 | | unsigned num_entities, BITCODE_RL size, |
6948 | | Bit_Chain *restrict dat, Dwg_Data *restrict dwg, |
6949 | | const EntitySectionIndexR11 entity_section) |
6950 | 5.44k | { |
6951 | 5.44k | int error = 0; |
6952 | 5.44k | BITCODE_BL num = dwg->num_objects; |
6953 | 5.44k | BITCODE_RL real_start = start; |
6954 | 5.44k | size_t oldpos; |
6955 | 5.44k | BITCODE_RLL hdr_handle = 0; |
6956 | 5.44k | const char *entities_section[] |
6957 | 5.44k | = { "entities", "blocks entities", "extras entities" }; |
6958 | 5.44k | Dwg_Object *hdr = NULL; |
6959 | 5.44k | Dwg_Object_BLOCK_HEADER *_hdr = NULL; |
6960 | 5.44k | BITCODE_BL block_idx = 0, hdr_index = 0; |
6961 | | |
6962 | 5.44k | LOG_TRACE ("\n%s: (" FORMAT_RLx "-" FORMAT_RLx " (%u), size " FORMAT_RL |
6963 | 5.44k | ")\n", |
6964 | 5.44k | entities_section[entity_section], start, end, num_entities, size); |
6965 | 5.44k | LOG_INFO ("==========================================\n"); |
6966 | | // we only have a 2nd entities_end, not for blocks nor extras |
6967 | 5.44k | if (end > dat->size && entity_section == ENTITIES_SECTION_INDEX |
6968 | 2.62k | && dwg->auxheader.entities_end && end != dwg->auxheader.entities_end) |
6969 | 0 | { |
6970 | 0 | LOG_ERROR ("Corrupt entities_end, fixed to " |
6971 | 0 | "auxheader.entities_end " FORMAT_RL, |
6972 | 0 | dwg->auxheader.entities_end); |
6973 | 0 | end = dwg->header.entities_end = dwg->auxheader.entities_end; |
6974 | 0 | } |
6975 | 5.44k | if (end > dat->size) |
6976 | 4.91k | { |
6977 | 4.91k | LOG_ERROR ("Corrupt end " FORMAT_RL " fixed to filesize", end); |
6978 | 4.91k | end = dat->size & 0xFFFFFFFF; |
6979 | 4.91k | if (start < end) |
6980 | 2.36k | size = end - start; |
6981 | 2.55k | else |
6982 | 2.55k | size = 0; |
6983 | 4.91k | } |
6984 | 5.44k | if (entity_section != BLOCKS_SECTION_INDEX) |
6985 | 4.09k | { |
6986 | 4.09k | hdr = dwg_model_space_object (dwg); |
6987 | 4.09k | if (hdr && hdr->fixedtype == DWG_TYPE_BLOCK_HEADER) |
6988 | 4.09k | { |
6989 | 4.09k | hdr_index = hdr->index; |
6990 | 4.09k | _hdr = hdr->tio.object->tio.BLOCK_HEADER; |
6991 | 4.09k | _hdr->block_offset_r11 = (BITCODE_RL)-1; |
6992 | 4.09k | if (!hdr->handle.value) |
6993 | 0 | hdr->handle.value = dwg_next_handle (dwg); |
6994 | 4.09k | hdr_handle = hdr->handle.value; |
6995 | 4.09k | LOG_TRACE ("owned by BLOCK %s (" FORMAT_HV ")\n", _hdr->name, |
6996 | 4.09k | hdr_handle); |
6997 | 4.09k | } |
6998 | 4.09k | } |
6999 | | // TODO search current offset in block_offset_r11 in BLOCK_HEADER's |
7000 | | |
7001 | | // with sentinel in case of R11 |
7002 | 5.44k | SINCE (R_11) |
7003 | 30 | { |
7004 | 30 | real_start -= 16; |
7005 | 30 | } |
7006 | | |
7007 | | // report unknown data before entities block |
7008 | 5.44k | if (start != end && real_start > 0 && (BITCODE_RL)dat->byte != real_start) |
7009 | 4.67k | { |
7010 | 4.67k | LOG_WARN ("\n@0x%zx => start 0x%x", dat->byte, real_start); |
7011 | 4.67k | if ((BITCODE_RL)dat->byte < real_start) |
7012 | 4.00k | { |
7013 | 4.00k | if (real_start > dat->size) |
7014 | 2.13k | { |
7015 | 2.13k | UNKNOWN_UNTIL (dat->size); |
7016 | 2.13k | } |
7017 | 1.86k | else |
7018 | 1.86k | { |
7019 | 1.86k | UNKNOWN_UNTIL (real_start); |
7020 | 1.86k | } |
7021 | 4.00k | } |
7022 | 4.67k | } |
7023 | | |
7024 | 5.44k | SINCE (R_11) |
7025 | 30 | { |
7026 | 30 | switch (entity_section) |
7027 | 30 | { |
7028 | 30 | case ENTITIES_SECTION_INDEX: |
7029 | 30 | DECODE_PRER13_SENTINEL (DWG_SENTINEL_R11_ENTITIES_BEGIN); |
7030 | 30 | break; |
7031 | 0 | case BLOCKS_SECTION_INDEX: |
7032 | 0 | DECODE_PRER13_SENTINEL (DWG_SENTINEL_R11_BLOCK_ENTITIES_BEGIN); |
7033 | 0 | break; |
7034 | 0 | case EXTRAS_SECTION_INDEX: |
7035 | 0 | DECODE_PRER13_SENTINEL (DWG_SENTINEL_R11_EXTRA_ENTITIES_BEGIN); |
7036 | 0 | break; |
7037 | 0 | default: |
7038 | 0 | LOG_ERROR ("Internal error: Illegal entity_section %d 0-2\n", |
7039 | 0 | (int)entity_section); |
7040 | 0 | return DWG_ERR_INTERNALERROR; |
7041 | 30 | } |
7042 | 30 | } |
7043 | | |
7044 | 5.44k | if (end > start && start == dat->byte) |
7045 | 2.14k | { |
7046 | 2.14k | oldpos = dat->byte; |
7047 | 2.14k | dat->bit = 0; |
7048 | 11.9M | while (dat->byte < oldpos + size) |
7049 | 11.9M | { |
7050 | 11.9M | size_t iter_start = dat->byte; |
7051 | 11.9M | Dwg_Object *obj; |
7052 | 11.9M | Dwg_Object_Type_r11 abstype; |
7053 | 11.9M | BITCODE_RC pline_flag; |
7054 | | |
7055 | 11.9M | if (!num) |
7056 | 0 | dwg->object |
7057 | 0 | = (Dwg_Object *)calloc (REFS_PER_REALLOC, sizeof (Dwg_Object)); |
7058 | 11.9M | else if (num >= dwg->num_alloced_objects) |
7059 | 1.99k | { |
7060 | 1.99k | if (num >= 10000000) |
7061 | 0 | { |
7062 | 0 | LOG_ERROR ("Too many objects, abort"); |
7063 | 0 | return DWG_ERR_VALUEOUTOFBOUNDS; |
7064 | 0 | } |
7065 | 3.99k | while (num >= dwg->num_alloced_objects) |
7066 | 1.99k | dwg->num_alloced_objects *= 2; |
7067 | 1.99k | dwg->object = (Dwg_Object *)realloc ( |
7068 | 1.99k | dwg->object, dwg->num_alloced_objects * sizeof (Dwg_Object)); |
7069 | 1.99k | LOG_TRACE ("REALLOC dwg->object vector to %u\n", |
7070 | 1.99k | dwg->num_alloced_objects); |
7071 | 1.99k | dwg->dirty_refs = 1; |
7072 | 1.99k | } |
7073 | 11.9M | if (!dwg->object) |
7074 | 0 | { |
7075 | 0 | LOG_ERROR ("Out of memory"); |
7076 | 0 | return DWG_ERR_OUTOFMEM; |
7077 | 0 | } |
7078 | 11.9M | obj = &dwg->object[num]; |
7079 | 11.9M | memset (obj, 0, sizeof (Dwg_Object)); |
7080 | 11.9M | dwg->num_objects++; |
7081 | 11.9M | obj->index = num; |
7082 | 11.9M | obj->parent = dwg; |
7083 | 11.9M | obj->address = dat->byte; |
7084 | 11.9M | if (entity_section == BLOCKS_SECTION_INDEX) |
7085 | 1.24M | obj->address |= 0x40000000; // to set entmode to 3 |
7086 | 11.9M | obj->supertype = DWG_SUPERTYPE_ENTITY; |
7087 | | |
7088 | 11.9M | LOG_HANDLE ("@offset 0x%zx\n", dat->byte - start); |
7089 | 11.9M | PRE (R_2_0b) |
7090 | 1.27M | { |
7091 | 1.27M | obj->type = bit_read_RS (dat); |
7092 | 1.27M | LOG_TRACE ("type: " FORMAT_RS " [RS]\n", obj->type); |
7093 | 1.27M | if (obj->type > 127) |
7094 | 230k | { // deleted. moved into BLOCK |
7095 | 230k | abstype = (Dwg_Object_Type_r11)abs ((int8_t)obj->type); |
7096 | 230k | LOG_TRACE ("deleted\n"); |
7097 | 230k | } |
7098 | 1.04M | else |
7099 | 1.04M | { |
7100 | 1.04M | abstype = (Dwg_Object_Type_r11)obj->type; |
7101 | 1.04M | } |
7102 | 1.27M | } |
7103 | 10.6M | else |
7104 | 10.6M | { |
7105 | 10.6M | obj->type = bit_read_RC (dat); |
7106 | 10.6M | LOG_TRACE ("type: " FORMAT_RCd " [RCd]\n", obj->type); |
7107 | 10.6M | if (obj->type > 127) |
7108 | 4.48M | { // deleted. moved into BLOCK |
7109 | 4.48M | abstype = (Dwg_Object_Type_r11)((unsigned)obj->type & 0x7F); |
7110 | 4.48M | LOG_TRACE ("deleted\n"); |
7111 | 4.48M | } |
7112 | 6.21M | else |
7113 | 6.21M | { |
7114 | 6.21M | abstype = (Dwg_Object_Type_r11)obj->type; |
7115 | 6.21M | } |
7116 | 10.6M | } |
7117 | | |
7118 | 11.9M | switch (abstype) |
7119 | 11.9M | { |
7120 | 66.5k | case DWG_TYPE_LINE_r11: |
7121 | 66.5k | error |= dwg_decode_LINE (dat, obj); |
7122 | 66.5k | break; |
7123 | 34.4k | case DWG_TYPE_POINT_r11: |
7124 | 34.4k | error |= dwg_decode_POINT (dat, obj); |
7125 | 34.4k | break; |
7126 | 16.4k | case DWG_TYPE_CIRCLE_r11: |
7127 | 16.4k | error |= dwg_decode_CIRCLE (dat, obj); |
7128 | 16.4k | break; |
7129 | 9.67k | case DWG_TYPE_SHAPE_r11: |
7130 | 9.67k | error |= dwg_decode_SHAPE (dat, obj); |
7131 | 9.67k | break; |
7132 | 34.8k | case DWG_TYPE_REPEAT_r11: |
7133 | 34.8k | error |= dwg_decode_REPEAT (dat, obj); |
7134 | 34.8k | break; |
7135 | 6.01k | case DWG_TYPE_ENDREP_r11: |
7136 | 6.01k | error |= dwg_decode_ENDREP (dat, obj); |
7137 | 6.01k | break; |
7138 | 33.2k | case DWG_TYPE_TEXT_r11: |
7139 | 33.2k | error |= dwg_decode_TEXT (dat, obj); |
7140 | 33.2k | break; |
7141 | 13.0k | case DWG_TYPE_ARC_r11: |
7142 | 13.0k | error |= dwg_decode_ARC (dat, obj); |
7143 | 13.0k | break; |
7144 | 15.7k | case DWG_TYPE_TRACE_r11: |
7145 | 15.7k | error |= dwg_decode_TRACE (dat, obj); |
7146 | 15.7k | break; |
7147 | 4.63k | case DWG_TYPE_LOAD_r11: |
7148 | 4.63k | error |= dwg_decode_LOAD (dat, obj); |
7149 | 4.63k | break; |
7150 | 4.85k | case DWG_TYPE_SOLID_r11: |
7151 | 4.85k | error |= dwg_decode_SOLID (dat, obj); |
7152 | 4.85k | break; |
7153 | 2.69k | case DWG_TYPE_BLOCK_r11: |
7154 | 2.69k | { |
7155 | 2.69k | BITCODE_RL cur_offset; |
7156 | 2.69k | BITCODE_RL cur_offset_prefix = 0; |
7157 | 2.69k | if (dat->version > R_2_22) |
7158 | 1.18k | cur_offset_prefix += 0x40000000; |
7159 | | // search current offset in block_offset_r11 in BLOCK_HEADER's |
7160 | | // and set new _hdr |
7161 | 2.69k | cur_offset = (((dat->byte - 1) - start) | cur_offset_prefix) |
7162 | 2.69k | & 0xFFFFFFFF; |
7163 | 2.69k | error |= dwg_decode_BLOCK (dat, obj); |
7164 | 2.69k | if (!_hdr && entity_section == BLOCKS_SECTION_INDEX) |
7165 | 459 | { |
7166 | 779k | for (BITCODE_BL i = 0; i < dwg->num_objects; i++) |
7167 | 778k | { |
7168 | 778k | Dwg_Object *o = &dwg->object[i]; |
7169 | 778k | if (o->fixedtype == DWG_TYPE_BLOCK_HEADER |
7170 | 548 | && o->tio.object && o->tio.object->tio.BLOCK_HEADER |
7171 | 548 | && cur_offset |
7172 | 548 | == o->tio.object->tio.BLOCK_HEADER |
7173 | 548 | ->block_offset_r11) |
7174 | 0 | { |
7175 | 0 | LOG_TRACE ("found BLOCK_HEADER \"%s\" at " |
7176 | 0 | "block_offset_r11 " |
7177 | 0 | "0x%x\n", |
7178 | 0 | o->tio.object->tio.BLOCK_HEADER->name, |
7179 | 0 | cur_offset); |
7180 | 0 | hdr = o; |
7181 | 0 | hdr_handle = hdr->handle.value; |
7182 | 0 | hdr_index = o->index; |
7183 | 0 | _hdr = o->tio.object->tio.BLOCK_HEADER; |
7184 | 0 | if (!obj->handle.value) |
7185 | 0 | obj->handle.value = dwg_next_handle (dwg); |
7186 | 0 | if (!_hdr->block_entity) |
7187 | 0 | _hdr->block_entity = dwg_add_handleref ( |
7188 | 0 | dwg, 3, obj->handle.value, obj); |
7189 | 0 | else |
7190 | 0 | { |
7191 | 0 | _hdr->block_entity->handleref.code = 3; |
7192 | 0 | _hdr->block_entity->absolute_ref |
7193 | 0 | = _hdr->block_entity->handleref.value |
7194 | 0 | = obj->handle.value; |
7195 | 0 | _hdr->block_entity->obj = obj; |
7196 | 0 | } |
7197 | 0 | LOG_TRACE ( |
7198 | 0 | "BLOCK_HEADER.block_entity: " FORMAT_HREF11 |
7199 | 0 | "\n", |
7200 | 0 | ARGS_HREF11 (_hdr->block_entity)); |
7201 | 0 | if (!obj->tio.entity->tio.BLOCK->name) |
7202 | 0 | obj->tio.entity->tio.BLOCK->name |
7203 | 0 | = strdup (_hdr->name); |
7204 | | // LOG_TRACE ("next entities owned by BLOCK \"%s\" |
7205 | | // (%lx)\n", |
7206 | | // _hdr->name, hdr_handle); |
7207 | 0 | block_idx++; |
7208 | 0 | break; |
7209 | 0 | } |
7210 | 778k | } |
7211 | 459 | if (!_hdr) |
7212 | 459 | { |
7213 | 459 | const char *name |
7214 | 459 | = obj->fixedtype == DWG_TYPE_BLOCK |
7215 | 459 | ? obj->tio.entity->tio.BLOCK->name |
7216 | 459 | : "(null)"; |
7217 | 459 | LOG_WARN ( |
7218 | 459 | "found no BLOCK_HEADER %s block_offset_r11 0x%x\n", |
7219 | 459 | name, cur_offset); |
7220 | 459 | hdr = NULL; |
7221 | 459 | } |
7222 | 459 | } |
7223 | 2.69k | } |
7224 | 2.69k | break; |
7225 | 3.83k | case DWG_TYPE_ENDBLK_r11: |
7226 | 3.83k | error |= dwg_decode_ENDBLK (dat, obj); |
7227 | 3.83k | if (_hdr) |
7228 | 236 | { |
7229 | 236 | hdr = &dwg->object[hdr_index]; |
7230 | 236 | _hdr->endblk_entity |
7231 | 236 | = dwg_add_handleref (dwg, 3, obj->handle.value, hdr); |
7232 | 236 | LOG_TRACE ("BLOCK_HEADER.endblk_entity: " FORMAT_HREF11 "\n", |
7233 | 236 | ARGS_HREF11 (_hdr->endblk_entity)); |
7234 | 236 | } |
7235 | 3.83k | hdr = NULL; |
7236 | 3.83k | _hdr = NULL; |
7237 | 3.83k | break; |
7238 | 20.9k | case DWG_TYPE_INSERT_r11: |
7239 | 20.9k | error |= dwg_decode_INSERT (dat, obj); |
7240 | 20.9k | break; |
7241 | 48.0k | case DWG_TYPE_ATTDEF_r11: |
7242 | 48.0k | error |= dwg_decode_ATTDEF (dat, obj); |
7243 | 48.0k | break; |
7244 | 47.3k | case DWG_TYPE_ATTRIB_r11: |
7245 | 47.3k | error |= dwg_decode_ATTRIB (dat, obj); |
7246 | 47.3k | break; |
7247 | 4.73k | case DWG_TYPE_SEQEND_r11: |
7248 | 4.73k | error |= dwg_decode_SEQEND (dat, obj); |
7249 | 4.73k | break; |
7250 | 1.14k | case DWG_TYPE_JUMP_r11: |
7251 | 1.14k | error |= dwg_decode_JUMP (dat, obj); |
7252 | 1.14k | break; |
7253 | 81.9k | case DWG_TYPE_POLYLINE_r11: |
7254 | 81.9k | { // which polyline |
7255 | 81.9k | BITCODE_RC flag_r11; |
7256 | 81.9k | BITCODE_RS opts_r11; |
7257 | 81.9k | BITCODE_RC extra_r11 = 0; |
7258 | 81.9k | BITCODE_RS eed_size; |
7259 | 81.9k | BITCODE_RC handling_len; |
7260 | 81.9k | size_t start_byte; |
7261 | 81.9k | LOG_TRACE ("Detect polyline:"); |
7262 | 81.9k | start_byte = dat->byte; |
7263 | 81.9k | LOG_TRACE (" start_byte: %" PRIuSIZE ",", start_byte); |
7264 | 81.9k | flag_r11 = bit_read_RC (dat); |
7265 | 81.9k | LOG_TRACE (" flag_r11: 0x%x,", flag_r11); |
7266 | 81.9k | dat->byte += 4; |
7267 | 81.9k | opts_r11 = bit_read_RS (dat); |
7268 | 81.9k | LOG_TRACE (" opts_r11: 0x%x", opts_r11); |
7269 | 81.9k | if (opts_r11 & OPTS_R11_POLYLINE_HAS_FLAG) |
7270 | 71.6k | { |
7271 | 71.6k | if (flag_r11 & FLAG_R11_HAS_PSPACE) |
7272 | 51.9k | { |
7273 | 51.9k | extra_r11 = bit_read_RC (dat); |
7274 | 51.9k | LOG_TRACE (", extra_r11: 0x%x", extra_r11); |
7275 | 51.9k | } |
7276 | 71.6k | if (flag_r11 & FLAG_R11_HAS_COLOR) |
7277 | 64.2k | dat->byte += 1; |
7278 | 71.6k | if (flag_r11 & FLAG_R11_HAS_LTYPE) |
7279 | 21.9k | { |
7280 | 21.9k | PRE (R_11) |
7281 | 21.4k | { |
7282 | 21.4k | dat->byte += 1; |
7283 | 21.4k | } |
7284 | 455 | else dat->byte += 2; |
7285 | 21.9k | } |
7286 | 71.6k | if (flag_r11 & FLAG_R11_HAS_THICKNESS) |
7287 | 25.8k | dat->byte += 8; |
7288 | 71.6k | if (flag_r11 & FLAG_R11_HAS_ELEVATION) |
7289 | 25.7k | dat->byte += 8; |
7290 | 71.6k | if (extra_r11 & EXTRA_R11_HAS_EED) |
7291 | 9.71k | { |
7292 | 9.71k | eed_size = bit_read_RS (dat); |
7293 | 9.71k | LOG_TRACE (", eed_size: %d", eed_size); |
7294 | 9.71k | dat->byte += eed_size; |
7295 | 9.71k | } |
7296 | 71.6k | if (flag_r11 & FLAG_R11_HAS_HANDLING) |
7297 | 55.3k | { |
7298 | 55.3k | handling_len = bit_read_RC (dat); |
7299 | 55.3k | LOG_TRACE (", handling_len: %d", handling_len); |
7300 | 55.3k | dat->byte += handling_len; |
7301 | 55.3k | } |
7302 | 71.6k | if (extra_r11 & EXTRA_R11_HAS_VIEWPORT) |
7303 | 23.1k | dat->byte += 2; |
7304 | 71.6k | pline_flag = bit_read_RC (dat); |
7305 | 71.6k | LOG_TRACE (", pline_flag: 0x%x", pline_flag); |
7306 | 71.6k | LOG_POS; |
7307 | 71.6k | dat->byte = start_byte; |
7308 | 71.6k | if (pline_flag & FLAG_POLYLINE_3D) |
7309 | 20.8k | error |= dwg_decode_POLYLINE_3D (dat, obj); |
7310 | 50.7k | else if (pline_flag & FLAG_POLYLINE_MESH) |
7311 | 21.6k | error |= dwg_decode_POLYLINE_MESH (dat, obj); |
7312 | 29.1k | else if (pline_flag & FLAG_POLYLINE_PFACE_MESH) |
7313 | 9.43k | error |= dwg_decode_POLYLINE_PFACE (dat, obj); |
7314 | 19.6k | else |
7315 | 19.6k | error |= dwg_decode_POLYLINE_2D (dat, obj); |
7316 | 71.6k | } |
7317 | 10.3k | else |
7318 | 10.3k | { |
7319 | 10.3k | dat->byte = start_byte; |
7320 | 10.3k | LOG_TRACE ("\n"); |
7321 | 10.3k | error |= dwg_decode_POLYLINE_2D (dat, obj); |
7322 | 10.3k | } |
7323 | 81.9k | } |
7324 | 81.9k | break; |
7325 | 59.5k | case DWG_TYPE_VERTEX_r11: |
7326 | 59.5k | { // which vertex? |
7327 | 59.5k | BITCODE_RC flag_r11; |
7328 | 59.5k | BITCODE_RS opts_r11; |
7329 | 59.5k | BITCODE_RC extra_r11 = 0; |
7330 | 59.5k | BITCODE_RS eed_size; |
7331 | 59.5k | BITCODE_RC handling_len; |
7332 | 59.5k | BITCODE_RC vertex_flag; |
7333 | 59.5k | size_t start_byte; |
7334 | 59.5k | LOG_TRACE ("Detect vertex:"); |
7335 | 59.5k | start_byte = dat->byte; |
7336 | 59.5k | LOG_TRACE (" start_byte: %" PRIuSIZE ",", start_byte); |
7337 | 59.5k | flag_r11 = bit_read_RC (dat); |
7338 | 59.5k | LOG_TRACE (" flag_r11: 0x%x,", flag_r11); |
7339 | 59.5k | dat->byte += 4; |
7340 | 59.5k | opts_r11 = bit_read_RS (dat); |
7341 | 59.5k | LOG_TRACE (" opts_r11: 0x%x", opts_r11); |
7342 | 59.5k | if (flag_r11 & FLAG_R11_HAS_COLOR) |
7343 | 10.7k | dat->byte += 1; |
7344 | 59.5k | if (flag_r11 & FLAG_R11_HAS_LTYPE) |
7345 | 14.4k | { |
7346 | 14.4k | PRE (R_11) |
7347 | 14.4k | { |
7348 | 14.4k | dat->byte += 1; |
7349 | 14.4k | } |
7350 | 32 | else dat->byte += 2; |
7351 | 14.4k | } |
7352 | 59.5k | if (flag_r11 & FLAG_R11_HAS_THICKNESS) |
7353 | 3.16k | dat->byte += 8; |
7354 | 59.5k | if (flag_r11 & FLAG_R11_HAS_ELEVATION) |
7355 | 46.3k | dat->byte += 8; |
7356 | 59.5k | if (flag_r11 & FLAG_R11_HAS_PSPACE) |
7357 | 2.73k | { |
7358 | 2.73k | extra_r11 = bit_read_RC (dat); |
7359 | 2.73k | LOG_TRACE (", extra_r11: 0x%x", extra_r11); |
7360 | 2.73k | } |
7361 | 59.5k | if (extra_r11 && extra_r11 & EXTRA_R11_HAS_EED) |
7362 | 1.52k | { |
7363 | 1.52k | eed_size = bit_read_RS (dat); |
7364 | 1.52k | LOG_TRACE (", eed_size: %d", eed_size); |
7365 | 1.52k | dat->byte += eed_size; |
7366 | 1.52k | } |
7367 | 59.5k | if (flag_r11 & FLAG_R11_HAS_HANDLING) |
7368 | 15.3k | { |
7369 | 15.3k | handling_len = bit_read_RC (dat); |
7370 | 15.3k | LOG_TRACE (", handling_len: %d", handling_len); |
7371 | 15.3k | dat->byte += handling_len; |
7372 | 15.3k | } |
7373 | 59.5k | if (extra_r11 && extra_r11 & EXTRA_R11_HAS_VIEWPORT) |
7374 | 1.50k | dat->byte += 2; |
7375 | 59.5k | if (!(opts_r11 & OPTS_R11_VERTEX_HAS_NOT_X_Y)) |
7376 | 44.3k | dat->byte += 16; |
7377 | 59.5k | if (opts_r11 & OPTS_R11_VERTEX_HAS_START_WIDTH) |
7378 | 36.9k | dat->byte += 8; |
7379 | 59.5k | if (opts_r11 & OPTS_R11_VERTEX_HAS_END_WIDTH) |
7380 | 26.0k | dat->byte += 8; |
7381 | 59.5k | if (opts_r11 & OPTS_R11_VERTEX_HAS_BULGE) |
7382 | 50.0k | dat->byte += 8; |
7383 | 59.5k | if (opts_r11 & OPTS_R11_VERTEX_HAS_FLAG) |
7384 | 33.3k | { |
7385 | 33.3k | vertex_flag = bit_read_RC (dat); |
7386 | 33.3k | LOG_TRACE (", vertex_flag: 0x%x", vertex_flag); |
7387 | 33.3k | LOG_POS; |
7388 | 33.3k | dat->byte = start_byte; |
7389 | 33.3k | if (vertex_flag & FLAG_VERTEX_MESH |
7390 | 9.74k | && vertex_flag & FLAG_VERTEX_PFACE_MESH) |
7391 | 5.56k | error |= dwg_decode_VERTEX_PFACE (dat, obj); |
7392 | 27.7k | else if (vertex_flag & FLAG_VERTEX_MESH) |
7393 | 4.17k | error |= dwg_decode_VERTEX_MESH (dat, obj); |
7394 | 23.5k | else if (vertex_flag & FLAG_VERTEX_PFACE_MESH) |
7395 | 4.32k | error |= dwg_decode_VERTEX_PFACE_FACE (dat, obj); |
7396 | 19.2k | else if (vertex_flag & FLAG_VERTEX_3D) |
7397 | 4.76k | error |= dwg_decode_VERTEX_3D (dat, obj); |
7398 | 14.4k | else |
7399 | 14.4k | error |= dwg_decode_VERTEX_2D (dat, obj); |
7400 | 33.3k | } |
7401 | 26.2k | else |
7402 | 26.2k | { |
7403 | 26.2k | dat->byte = start_byte; |
7404 | 26.2k | LOG_TRACE ("\n"); |
7405 | 26.2k | error |= dwg_decode_VERTEX_2D (dat, obj); |
7406 | 26.2k | } |
7407 | 59.5k | } |
7408 | 59.5k | break; |
7409 | 64.5k | case DWG_TYPE_3DLINE_r11: |
7410 | 64.5k | error |= dwg_decode__3DLINE (dat, obj); |
7411 | 64.5k | break; |
7412 | 33.5k | case DWG_TYPE_3DFACE_r11: |
7413 | 33.5k | error |= dwg_decode__3DFACE (dat, obj); |
7414 | 33.5k | break; |
7415 | 201k | case DWG_TYPE_DIMENSION_r11: |
7416 | 201k | error |= decode_preR13_DIMENSION (dat, obj); |
7417 | 201k | break; |
7418 | 5.52k | case DWG_TYPE_VIEWPORT_r11: |
7419 | 5.52k | error |= dwg_decode_VIEWPORT (dat, obj); |
7420 | 5.52k | break; |
7421 | 11.1M | default: |
7422 | 11.1M | dat->byte--; |
7423 | 11.1M | DEBUG_HERE; |
7424 | 11.1M | obj->type |
7425 | 11.1M | = (BITCODE_BS)(DWG_TYPE_UNKNOWN_r11 | (obj->type & 0x80)); |
7426 | 11.1M | obj->fixedtype = DWG_TYPE_UNKNOWN_ENT; |
7427 | 11.1M | error |= DWG_ERR_SECTIONNOTFOUND; |
7428 | 11.1M | dat->byte++; |
7429 | 11.1M | if (dat->byte >= dat->size) |
7430 | 342 | { |
7431 | 342 | LOG_ERROR ("%s buffer overflow at %" PRIuSIZE |
7432 | 342 | ".%u >= %" PRIuSIZE, |
7433 | 342 | __FUNCTION__, dat->byte, dat->bit, dat->size); |
7434 | 342 | return DWG_ERR_INVALIDDWG; |
7435 | 342 | } |
7436 | 11.1M | break; |
7437 | 11.9M | } |
7438 | | |
7439 | 11.9M | assert (!dat->bit); |
7440 | 11.9M | PRE (R_2_0b) |
7441 | 1.27M | { |
7442 | 1.27M | obj->size = (dat->byte - obj->address) & 0xFFFFFFFF; |
7443 | 1.27M | if (num + 1 > dwg->num_objects) |
7444 | 0 | break; |
7445 | 1.27M | } |
7446 | 11.9M | if (obj->type != DWG_TYPE_JUMP_r11) |
7447 | 11.9M | { |
7448 | 11.9M | SINCE (R_2_0b) // Pre R_2_0 doesn't contain size of entity |
7449 | 10.6M | { |
7450 | 10.6M | PRE (R_11) // no crc16 |
7451 | 10.6M | { |
7452 | 10.6M | if (obj->size > dat->size - obj->address |
7453 | 10.5M | || obj->size + obj->address > dat->byte + 1) |
7454 | 1.45M | { |
7455 | 1.45M | LOG_ERROR ("Invalid obj->size " FORMAT_RL |
7456 | 1.45M | " changed to %" PRIuSIZE, |
7457 | 1.45M | obj->size, dat->byte - obj->address); |
7458 | 1.45M | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
7459 | 1.45M | obj->size = (dat->byte - obj->address) & 0xFFFFFFFF; |
7460 | 1.45M | } |
7461 | 9.22M | else if (obj->address + obj->size != dat->byte) |
7462 | 9.22M | { |
7463 | 9.22M | LOG_ERROR ("offset %ld", |
7464 | 9.22M | (long)(obj->address + obj->size - dat->byte)); |
7465 | 9.22M | if (obj->address + obj->size > dat->byte) |
7466 | 1.57k | { |
7467 | 1.57k | BITCODE_RL offset |
7468 | 1.57k | = (BITCODE_RL)(obj->address + obj->size |
7469 | 1.57k | - dat->byte); |
7470 | 1.57k | obj->num_unknown_rest = 8 * offset; |
7471 | 1.57k | obj->unknown_rest = (BITCODE_TF)calloc (offset, 1); |
7472 | 1.57k | if (obj->unknown_rest) |
7473 | 1.57k | { |
7474 | 1.57k | memcpy (obj->unknown_rest, |
7475 | 1.57k | &dat->chain[dat->byte], offset); |
7476 | 1.57k | LOG_TRACE_TF (obj->unknown_rest, offset); |
7477 | 1.57k | } |
7478 | 0 | else |
7479 | 0 | { |
7480 | 0 | LOG_ERROR ("Out of memory"); |
7481 | 0 | obj->num_unknown_rest = 0; |
7482 | 0 | } |
7483 | 1.57k | } |
7484 | 9.22M | if (obj->size > 2) |
7485 | 374k | dat->byte = obj->address + obj->size; |
7486 | 9.22M | } |
7487 | 10.6M | } |
7488 | 22.0k | LATER_VERSIONS |
7489 | 22.0k | { |
7490 | 22.0k | if (obj->size > dat->size - obj->address |
7491 | 20.6k | || obj->size + obj->address > dat->byte + 2) |
7492 | 1.64k | { |
7493 | 1.64k | LOG_ERROR ("Invalid obj->size " FORMAT_RL |
7494 | 1.64k | " changed to %" PRIuSIZE, |
7495 | 1.64k | obj->size, dat->byte + 2 - obj->address); |
7496 | 1.64k | error |= DWG_ERR_VALUEOUTOFBOUNDS; |
7497 | 1.64k | obj->size |
7498 | 1.64k | = ((dat->byte + 2) - obj->address) & 0xFFFFFFFF; |
7499 | 1.64k | } |
7500 | 20.3k | else if (obj->address + obj->size != dat->byte + 2) |
7501 | 20.3k | { |
7502 | 20.3k | LOG_ERROR ("offset %ld", (long)(obj->address + obj->size |
7503 | 20.3k | - (dat->byte + 2))); |
7504 | 20.3k | if (obj->address + obj->size > dat->byte + 2) |
7505 | 0 | { |
7506 | 0 | BITCODE_RL offset |
7507 | 0 | = (BITCODE_RL)(obj->address + obj->size |
7508 | 0 | - (dat->byte + 2)); |
7509 | 0 | obj->num_unknown_rest = 8 * offset; |
7510 | 0 | obj->unknown_rest = bit_read_TF (dat, offset); |
7511 | 0 | if (obj->unknown_rest) |
7512 | 0 | { |
7513 | 0 | LOG_TRACE_TF (obj->unknown_rest, offset); |
7514 | 0 | } |
7515 | 0 | else |
7516 | 0 | { |
7517 | 0 | LOG_ERROR ("Out of memory"); |
7518 | 0 | obj->num_unknown_rest = 0; |
7519 | 0 | } |
7520 | 0 | } |
7521 | 20.3k | if (obj->address + obj->size >= start && start > 60 |
7522 | 20.3k | && obj->address + obj->size - 2 > dat->byte) |
7523 | 0 | dat->byte = obj->address + obj->size - 2; |
7524 | 20.3k | } |
7525 | 22.0k | if (!bit_check_CRC (dat, obj->address, 0xC0C1)) |
7526 | 22.0k | error |= DWG_ERR_WRONGCRC; |
7527 | 22.0k | } |
7528 | 10.6M | } |
7529 | 11.9M | } |
7530 | | // add to block header |
7531 | 11.9M | if (_hdr && obj->supertype == DWG_SUPERTYPE_ENTITY && obj->tio.entity |
7532 | 685k | && obj->fixedtype != DWG_TYPE_UNUSED |
7533 | 685k | && obj->fixedtype != DWG_TYPE_JUMP |
7534 | 684k | && obj->type != DWG_TYPE_VERTEX_r11 |
7535 | 639k | && obj->fixedtype != DWG_TYPE_SEQEND) |
7536 | 635k | { |
7537 | 635k | BITCODE_H ref; |
7538 | 635k | if (!obj->handle.value) |
7539 | 18.2k | obj->handle.value = dwg_next_handle (dwg); |
7540 | 635k | hdr = &dwg->object[hdr_index]; |
7541 | 635k | ref = dwg_add_handleref (dwg, 3, obj->handle.value, hdr); |
7542 | | // if (dwg->dirty_refs) |
7543 | | // find _hdr again from hdr_handle |
7544 | 635k | LOG_TRACE ("BLOCK_HEADER \"%s\".", _hdr->name); |
7545 | 635k | if (obj->fixedtype != DWG_TYPE_BLOCK) |
7546 | 634k | PUSH_HV (_hdr, num_owned, entities, ref); |
7547 | 635k | obj->tio.entity->ownerhandle |
7548 | 635k | = dwg_add_handleref (dwg, 4, hdr_handle, obj); |
7549 | 635k | obj->tio.entity->ownerhandle->r11_idx = block_idx; |
7550 | 635k | LOG_TRACE ("ownerhandle: " FORMAT_HREF11 "\n", |
7551 | 635k | ARGS_HREF11 (obj->tio.entity->ownerhandle)); |
7552 | 635k | } |
7553 | 11.9M | num++; |
7554 | 11.9M | if (dat->byte < oldpos + size) |
7555 | 11.9M | LOG_TRACE ("\n"); |
7556 | 11.9M | if (dat->byte >= dat->size && (BITCODE_RL)dat->byte != end) |
7557 | 367 | { |
7558 | 367 | LOG_ERROR ("Too many entities, buffer overflow %" PRIuSIZE |
7559 | 367 | " >= %" PRIuSIZE, |
7560 | 367 | dat->byte, dat->size); |
7561 | 367 | return DWG_ERR_INVALIDDWG; |
7562 | 367 | } |
7563 | 11.9M | if (dat->byte == iter_start) |
7564 | 0 | { |
7565 | 0 | LOG_ERROR ( |
7566 | 0 | "No advance in decode_preR13_entities, abort at %" PRIuSIZE, |
7567 | 0 | dat->byte); |
7568 | 0 | return DWG_ERR_INVALIDDWG; |
7569 | 0 | } |
7570 | 11.9M | } |
7571 | 1.43k | if ((BITCODE_RL)dat->byte != end) |
7572 | 1 | { |
7573 | 1 | LOG_ERROR ("@0x%zx => end 0x%x", dat->byte, end); |
7574 | 1 | return DWG_ERR_INVALIDDWG; |
7575 | 1 | } |
7576 | 1.43k | } |
7577 | | |
7578 | 4.73k | SINCE (R_11) |
7579 | 21 | { |
7580 | 21 | switch (entity_section) |
7581 | 21 | { |
7582 | 21 | case ENTITIES_SECTION_INDEX: |
7583 | 21 | DECODE_PRER13_SENTINEL (DWG_SENTINEL_R11_ENTITIES_END); |
7584 | 21 | break; |
7585 | 0 | case BLOCKS_SECTION_INDEX: |
7586 | 0 | DECODE_PRER13_SENTINEL (DWG_SENTINEL_R11_BLOCK_ENTITIES_END); |
7587 | 0 | break; |
7588 | 0 | case EXTRAS_SECTION_INDEX: |
7589 | 0 | DECODE_PRER13_SENTINEL (DWG_SENTINEL_R11_EXTRA_ENTITIES_END); |
7590 | 0 | break; |
7591 | 0 | default: |
7592 | 0 | LOG_ERROR ("Internal error: Illegal entity_section %d 0-2\n", |
7593 | 0 | (int)entity_section); |
7594 | 0 | return DWG_ERR_INTERNALERROR; |
7595 | 21 | } |
7596 | 21 | } |
7597 | | |
7598 | 4.73k | LOG_INFO ("==========================================\n"); |
7599 | 4.73k | LOG_TRACE ("%s: end\n", entities_section[entity_section]); |
7600 | | |
7601 | 4.73k | return error; |
7602 | 4.73k | } |
7603 | | |
7604 | | #undef IS_DECODER |