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