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