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