1 /*****************************************************************************/
2 /*  LibreDWG - free implementation of the DWG file format                    */
3 /*                                                                           */
4 /*  Copyright (C) 2010-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_r2007.c: functions to decode R2007 (AC1021) sections
15  * written by Till Heuschmann
16  * modified by Reini Urban
17  */
18 
19 #define IS_DECODER
20 
21 #include "config.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdint.h>
26 #include <sys/types.h>
27 #include <stdbool.h>
28 #include <assert.h>
29 #include "common.h"
30 #include "bits.h"
31 #include "decode.h"
32 #include "dynapi.h"
33 
34 /* The logging level for the read (decode) path.  */
35 static unsigned int loglevel;
36 /* the current version per spec block */
37 static unsigned int cur_ver = 0;
38 
39 #define DWG_LOGLEVEL loglevel
40 #include "logging.h"
41 #include "dec_macros.h"
42 
43 // only for temp. debugging, to abort on obviously wrong sizes.
44 // should be a bit larger then the filesize.
45 #define DBG_MAX_COUNT 0x100000
46 #define DBG_MAX_SIZE 0xff0000 /* should be dat->size */
47 
48 typedef struct r2007_file_header
49 {
50   int64_t header_size; // 0x70
51   int64_t file_size;
52   int64_t pages_map_crc_compressed;
53   int64_t pages_map_correction;
54   int64_t pages_map_crc_seed;
55   int64_t pages_map2_offset;
56   int64_t pages_map2_id;
57   int64_t pages_map_offset; // starting address of the Page Map section
58   int64_t pages_map_id;
59   int64_t header2_offset;
60   int64_t pages_map_size_comp; // the compressed size of section
61   int64_t pages_map_size_uncomp;
62   int64_t pages_amount;
63   int64_t pages_maxid;
64   int64_t unknown1; // 0x20
65   int64_t unknown2; // 0x40
66   int64_t pages_map_crc_uncomp;
67   int64_t unknown3; // 0xf800
68   int64_t unknown4; // 4
69   int64_t unknown5; // 1
70   int64_t num_sections;
71   int64_t sections_map_crc_uncomp;
72   int64_t sections_map_size_comp;
73   int64_t sections_map2_id;
74   int64_t sections_map_id;
75   int64_t sections_map_size_uncomp;
76   int64_t sections_map_crc_comp;
77   int64_t sections_map_correction;
78   int64_t sections_map_crc_seed;
79   int64_t stream_version; // 0x60100
80   int64_t crc_seed;
81   int64_t crc_seed_encoded;
82   int64_t random_seed;
83   int64_t header_crc;
84 } r2007_file_header;
85 
86 /* page map */
87 typedef struct _r2007_page
88 {
89   int64_t id;
90   uint64_t size;
91   uint64_t offset;
92   struct _r2007_page *next;
93 } r2007_page;
94 
95 /* section page */
96 typedef struct _r2007_section_page
97 {
98   uint64_t offset;
99   uint64_t size;
100   int64_t id;
101   uint64_t uncomp_size; // src_size
102   uint64_t comp_size;
103   uint64_t checksum;
104   uint64_t crc;
105 } r2007_section_page;
106 
107 /* section map */
108 typedef struct _r2007_section
109 {
110   uint64_t data_size; // max size of page
111   uint64_t max_size;
112   int64_t encrypted;
113   uint64_t hashcode;   // checksum in r2004
114   int64_t name_length; // 0x22
115   int64_t unknown;     // 0x00
116   int64_t encoded;
117   int64_t num_pages;
118   DWGCHAR *name;
119   Dwg_Section_Type type;
120   r2007_section_page **pages;
121   struct _r2007_section *next;
122 } r2007_section;
123 
124 /* imported */
125 int rs_decode_block (BITCODE_RC *blk, int fix);
126 
127 /* private */
128 static r2007_section *get_section (r2007_section *sections_map,
129                                    Dwg_Section_Type sec_type);
130 static r2007_page *get_page (r2007_page *pages_map, int64_t id);
131 static void pages_destroy (r2007_page *page);
132 static void sections_destroy (r2007_section *section);
133 static r2007_section *read_sections_map (Bit_Chain *dat, int64_t size_comp,
134                                          int64_t size_uncomp,
135                                          int64_t correction) ATTRIBUTE_MALLOC;
136 static int read_data_section (Bit_Chain *sec_dat, Bit_Chain *dat,
137                               r2007_section *restrict sections_map,
138                               r2007_page *restrict pages_map,
139                               Dwg_Section_Type sec_type);
140 static int read_2007_section_classes (Bit_Chain *restrict dat,
141                                       Dwg_Data *restrict dwg,
142                                       r2007_section *restrict sections_map,
143                                       r2007_page *restrict pages_map);
144 static int read_2007_section_header (Bit_Chain *dat, Bit_Chain *hdl_dat,
145                                      Dwg_Data *restrict dwg,
146                                      r2007_section *restrict sections_map,
147                                      r2007_page *restrict pages_map);
148 static int read_2007_section_handles (Bit_Chain *dat, Bit_Chain *hdl_dat,
149                                       Dwg_Data *restrict dwg,
150                                       r2007_section *restrict sections_map,
151                                       r2007_page *restrict pages_map);
152 static int read_2007_section_summary (Bit_Chain *restrict dat,
153                                       Dwg_Data *restrict dwg,
154                                       r2007_section *restrict sections_map,
155                                       r2007_page *restrict pages_map);
156 static int read_2007_section_preview (Bit_Chain *restrict dat,
157                                       Dwg_Data *restrict dwg,
158                                       r2007_section *restrict sections_map,
159                                       r2007_page *restrict pages_map);
160 static r2007_page *read_pages_map (Bit_Chain *dat, int64_t size_comp,
161                                    int64_t size_uncomp,
162                                    int64_t correction) ATTRIBUTE_MALLOC;
163 static int read_file_header (Bit_Chain *restrict dat,
164                              r2007_file_header *restrict file_header);
165 static void read_instructions (BITCODE_RC *restrict *restrict src,
166                                BITCODE_RC *restrict opcode,
167                                uint32_t *restrict offset,
168                                uint32_t *restrict length);
169 static inline BITCODE_RC *copy_bytes_2 (BITCODE_RC *restrict dst,
170                                         const BITCODE_RC *restrict src);
171 static inline BITCODE_RC *copy_bytes_3 (BITCODE_RC *restrict dst,
172                                         const BITCODE_RC *restrict src);
173 static void copy_bytes (BITCODE_RC *dst, uint32_t length, uint32_t offset);
174 static uint32_t read_literal_length (BITCODE_RC *restrict *restrict src,
175                                      unsigned char opcode);
176 static void copy_compressed_bytes (BITCODE_RC *restrict dst,
177                                    BITCODE_RC *restrict src,
178                                    int length);
179 static DWGCHAR *bfr_read_string (BITCODE_RC *restrict *restrict src,
180                                  int64_t size) ATTRIBUTE_MALLOC;
181 static BITCODE_RC *decode_rs (const BITCODE_RC *src, int block_count,
182                               int data_size, const unsigned src_size) ATTRIBUTE_MALLOC;
183 static int decompress_r2007 (BITCODE_RC *restrict dst, const unsigned dst_size,
184                              BITCODE_RC *restrict src, const unsigned src_size);
185 
186 #define copy_1(offset) *dst++ = *(src + offset);
187 
188 #define copy_2(offset) dst = copy_bytes_2 (dst, src + offset);
189 
190 #define copy_3(offset) dst = copy_bytes_3 (dst, src + offset)
191 
192 // 4 and 8 is not reverse, 16 is
193 #define copy_n(n, offset)                                                     \
194   memcpy (dst, &src[offset], n);                                              \
195   dst += n
196 
197 #define copy_4(offset) copy_n (4, offset)
198 #define copy_8(offset) copy_n (8, offset)
199 #define copy_16(offset)                                                       \
200   memcpy (dst, &src[offset + 8], 8);                                          \
201   memcpy (&dst[8], &src[offset], 8);                                          \
202   dst += 16
203 
204 /* Don't use restrict here: GH #141 broken for most newer compilers */
205 static inline BITCODE_RC *
copy_bytes_2(BITCODE_RC * dst,const BITCODE_RC * src)206 copy_bytes_2 (BITCODE_RC *dst, const BITCODE_RC *src)
207 {
208   dst[0] = src[1];
209   dst[1] = src[0];
210   return dst + 2;
211 }
212 
213 static inline BITCODE_RC *
copy_bytes_3(BITCODE_RC * dst,const BITCODE_RC * src)214 copy_bytes_3 (BITCODE_RC *dst, const BITCODE_RC *src)
215 {
216   dst[0] = src[2];
217   dst[1] = src[1];
218   dst[2] = src[0];
219   return dst + 3;
220 }
221 
222 static void
copy_bytes(BITCODE_RC * dst,uint32_t length,uint32_t offset)223 copy_bytes (BITCODE_RC *dst, uint32_t length, uint32_t offset)
224 {
225   BITCODE_RC *src = dst - offset;
226 
227   while (length-- > 0)
228     *dst++ = *src++;
229 }
230 
231 /* See spec version 5.0 page 30 */
232 static void
copy_compressed_bytes(BITCODE_RC * restrict dst,BITCODE_RC * restrict src,int length)233 copy_compressed_bytes (BITCODE_RC *restrict dst, BITCODE_RC *restrict src,
234                        int length)
235 {
236   while (length >= 32)
237     {
238       copy_16 (16);
239       copy_16 (0);
240 
241       src += 32;
242       length -= 32;
243     }
244 
245   switch (length)
246     {
247     case 0:
248       break;
249     case 1:
250       copy_1 (0);
251       break;
252     case 2:
253       copy_2 (0);
254       break;
255     case 3:
256       copy_3 (0);
257       break;
258     case 4:
259       copy_4 (0);
260       break;
261     case 5:
262       copy_1 (4);
263       copy_4 (0);
264       break;
265     case 6:
266       copy_1 (5);
267       copy_4 (1);
268       copy_1 (0);
269       break;
270     case 7:
271       copy_2 (5);
272       copy_4 (1);
273       copy_1 (0);
274       break;
275     case 8:
276       copy_8 (0);
277       break;
278     case 9:
279       copy_1 (8);
280       copy_8 (0);
281       break;
282     case 10:
283       copy_1 (9);
284       copy_8 (1);
285       copy_1 (0);
286       break;
287     case 11:
288       copy_2 (9);
289       copy_8 (1);
290       copy_1 (0);
291       break;
292     case 12:
293       copy_4 (8);
294       copy_8 (0);
295       break;
296     case 13:
297       copy_1 (12);
298       copy_4 (8);
299       copy_8 (0);
300       break;
301     case 14:
302       copy_1 (13);
303       copy_4 (9);
304       copy_8 (1);
305       copy_1 (0);
306       break;
307     case 15:
308       copy_2 (13);
309       copy_4 (9);
310       copy_8 (1);
311       copy_1 (0);
312       break;
313     case 16:
314       copy_16 (0);
315       break;
316     case 17:
317       copy_8 (9);
318       copy_1 (8);
319       copy_8 (0);
320       break;
321     case 18:
322       copy_1 (17);
323       copy_16 (1);
324       copy_1 (0);
325       break;
326     case 19:
327       copy_3 (16);
328       copy_16 (0);
329       break;
330     case 20:
331       copy_4 (16);
332       copy_16 (0);
333       break;
334     case 21:
335       copy_1 (20);
336       copy_4 (16);
337       copy_16 (0);
338       break;
339     case 22:
340       copy_2 (20);
341       copy_4 (16);
342       copy_16 (0);
343       break;
344     case 23:
345       copy_3 (20);
346       copy_4 (16);
347       copy_16 (0);
348       break;
349     case 24:
350       copy_8 (16);
351       copy_16 (0);
352       break;
353     case 25:
354       copy_8 (17);
355       copy_1 (16);
356       copy_16 (0);
357       break;
358     case 26:
359       copy_1 (25);
360       copy_8 (17);
361       copy_1 (16);
362       copy_16 (0);
363       break;
364     case 27:
365       copy_2 (25);
366       copy_8 (17);
367       copy_1 (16);
368       copy_16 (0);
369       break;
370     case 28:
371       copy_4 (24);
372       copy_8 (16);
373       copy_16 (0);
374       break;
375     case 29:
376       copy_1 (28);
377       copy_4 (24);
378       copy_8 (16);
379       copy_16 (0);
380       break;
381     case 30:
382       copy_2 (28);
383       copy_4 (24);
384       copy_8 (16);
385       copy_16 (0);
386       break;
387     case 31:
388       copy_1 (30);
389       copy_4 (26);
390       copy_8 (18);
391       copy_16 (2);
392       copy_2 (0);
393       break;
394     default:
395       LOG_ERROR ("Wrong length %d", length);
396     }
397 }
398 
399 /* See spec version 5.1 page 50 */
400 static uint32_t
read_literal_length(BITCODE_RC * restrict * src,unsigned char opcode)401 read_literal_length (BITCODE_RC *restrict *src, unsigned char opcode)
402 {
403   uint32_t length = opcode + 8;
404 
405   if (length == 0x17)
406     {
407       int n = *(*src)++;
408 
409       length += n;
410 
411       if (n == 0xff)
412         {
413           do
414             {
415               n = *(*src)++;
416               n |= (*(*src)++ << 8);
417 
418               length += n;
419             }
420           while (n == 0xFFFF);
421         }
422     }
423 
424   return length;
425 }
426 
427 /* See spec version 5.1 page 53 */
428 static void
read_instructions(BITCODE_RC * restrict * src,unsigned char * restrict opcode,uint32_t * restrict offset,uint32_t * restrict length)429 read_instructions (BITCODE_RC *restrict *src, unsigned char *restrict opcode,
430                    uint32_t *restrict offset, uint32_t *restrict length)
431 {
432   switch (*opcode >> 4)
433     {
434     case 0:
435       *length = (*opcode & 0xf) + 0x13;
436       *offset = *(*src)++;
437       *opcode = *(*src)++;
438       *length = ((*opcode >> 3) & 0x10) + *length;
439       *offset = ((*opcode & 0x78) << 5) + 1 + *offset;
440       break;
441 
442     case 1:
443       *length = (*opcode & 0xf) + 3;
444       *offset = *(*src)++;
445       *opcode = *(*src)++;
446       *offset = ((*opcode & 0xf8) << 5) + 1 + *offset;
447       break;
448 
449     case 2:
450       *offset = *(*src)++;
451       *offset = ((*(*src)++ << 8) & 0xff00) | *offset;
452       *length = *opcode & 7;
453 
454       if ((*opcode & 8) == 0)
455         {
456           *opcode = *(*src)++;
457           *length = (*opcode & 0xf8) + *length;
458         }
459       else
460         {
461           (*offset)++;
462           *length = (*(*src)++ << 3) + *length;
463           *opcode = *(*src)++;
464           *length = (((*opcode & 0xf8) << 8) + *length) + 0x100;
465         }
466       break;
467 
468     default:
469       *length = *opcode >> 4;
470       *offset = *opcode & 15;
471       *opcode = *(*src)++;
472       *offset = (((*opcode & 0xf8) << 1) + *offset) + 1;
473       break;
474     }
475 }
476 
477 /* par 4.7 Compression, page 32 (same as format 2004)
478    TODO: replace by decompress_R2004_section(dat, decomp, comp_data_size)
479 */
480 static int
decompress_r2007(BITCODE_RC * restrict dst,const unsigned dst_size,BITCODE_RC * restrict src,const unsigned src_size)481 decompress_r2007 (BITCODE_RC *restrict dst, const unsigned dst_size,
482                   BITCODE_RC *restrict src, const unsigned src_size)
483 {
484   uint32_t length = 0;
485   uint32_t offset = 0;
486 
487   BITCODE_RC *dst_start = dst;
488   BITCODE_RC *dst_end = dst + dst_size;
489   BITCODE_RC *src_end = src + src_size;
490   unsigned char opcode;
491 
492   LOG_INSANE ("decompress_r2007 (%p, %d, %p, %d)\n", dst, dst_size, src, src_size);
493   if (!dst || !src || !dst_size || src_size < 2)
494     {
495       LOG_ERROR ("Invalid argument to %s\n", __FUNCTION__);
496       return DWG_ERR_INTERNALERROR;
497     }
498 
499   opcode = *src++;
500   if ((opcode & 0xf0) == 0x20)
501     {
502       src += 2;
503       length = *src++ & 0x07;
504       if (length == 0)
505         {
506           LOG_ERROR ("Decompression error: zero length")
507           return DWG_ERR_INTERNALERROR;
508         }
509     }
510 
511   while (src < src_end)
512     {
513       if (length == 0)
514         length = read_literal_length (&src, opcode);
515 
516       if ((dst + length) > dst_end || (src + length) > src_end)
517         {
518           LOG_ERROR ("Decompression error: length overflow");
519           return DWG_ERR_INTERNALERROR;
520         }
521 
522       LOG_INSANE("copy_compressed_bytes (%p, %p, %u)\n", dst, src, length);
523       copy_compressed_bytes (dst, src, length);
524 
525       dst += length;
526       src += length;
527 
528       length = 0;
529 
530       if (src >= src_end)
531         return 0;
532 
533       opcode = *src++;
534 
535       read_instructions (&src, &opcode, &offset, &length);
536 
537       while (1)
538         {
539           if ((dst + length) > dst_end)
540             {
541               LOG_ERROR ("Decompression error: length overflow");
542               return DWG_ERR_INTERNALERROR;
543             }
544           if (offset > (uint32_t) (dst - dst_start))
545             {
546               LOG_ERROR ("Decompression error: offset underflow");
547               return DWG_ERR_INTERNALERROR;
548             }
549           LOG_INSANE ("copy_bytes (%p, %u, %u)\n", dst, length, offset);
550           copy_bytes (dst, length, offset);
551 
552           dst += length;
553           length = (opcode & 7);
554 
555           if (length != 0 || src >= src_end)
556             break;
557 
558           opcode = *src++;
559 
560           if ((opcode >> 4) == 0)
561             break;
562 
563           if ((opcode >> 4) == 0x0f)
564             opcode &= 0xf;
565 
566           read_instructions ((unsigned char **)&src, &opcode, &offset,
567                              &length);
568         }
569     }
570 
571   return 0;
572 }
573 
574 // reed-solomon (255, 239) encoding with factor 3
575 // TODO: for now disabled, until we get proper data
576 ATTRIBUTE_MALLOC
577 static BITCODE_RC *
decode_rs(const BITCODE_RC * src,int block_count,int data_size,const unsigned src_size)578 decode_rs (const BITCODE_RC *src, int block_count, int data_size,
579            const unsigned src_size)
580 {
581   int i, j;
582   const BITCODE_RC *src_base = src;
583   BITCODE_RC *dst_base, *dst;
584   // TODO: round up data_size from 239 to 255
585 
586   if ((unsigned long)block_count * data_size > src_size)
587     {
588       LOG_ERROR ("decode_rs src overflow: %ld > %u",
589                  (long)block_count * data_size, src_size)
590       return NULL;
591     }
592   dst_base = dst = (BITCODE_RC *)calloc (block_count, data_size);
593   if (!dst)
594     {
595       LOG_ERROR ("Out of memory")
596       return NULL;
597     }
598 
599   for (i = 0; i < block_count; ++i)
600     {
601       for (j = 0; j < data_size; ++j)
602         {
603           *dst++ = *src;
604           src += block_count;
605         }
606 
607       // rs_decode_block((unsigned char*)(dst_base + 239*i), 1);
608       src = ++src_base;
609     }
610 
611   return dst_base;
612 }
613 
614 ATTRIBUTE_MALLOC
615 static BITCODE_RC *
read_system_page(Bit_Chain * dat,int64_t size_comp,int64_t size_uncomp,int64_t repeat_count)616 read_system_page (Bit_Chain *dat, int64_t size_comp, int64_t size_uncomp,
617                   int64_t repeat_count)
618 {
619   int i;
620   int error = 0;
621 
622   int64_t pesize;      // Pre RS encoded size
623   int64_t block_count; // Number of RS encoded blocks
624   int64_t page_size;
625   long pedata_size;
626 
627   BITCODE_RC *rsdata; // RS encoded data
628   BITCODE_RC *pedata; // Pre RS encoded data
629   BITCODE_RC *data;   // The data RS unencoded and uncompressed
630 
631   if (repeat_count < 0 ||
632       repeat_count > DBG_MAX_COUNT ||
633       (uint64_t)size_comp >= dat->size ||
634       (uint64_t)size_uncomp >= dat->size)
635     {
636       LOG_ERROR ("Invalid r2007 system page: "
637                  "size_comp: %" PRId64 ", size_uncomp: %" PRId64
638                  ", repeat_count: %" PRId64, size_comp, size_uncomp, repeat_count);
639       return NULL;
640     }
641   // Round to a multiple of 8
642   pesize = ((size_comp + 7) & ~7) * repeat_count;
643   // Divide pre encoded size by RS k-value (239)
644   block_count = (pesize + 238) / 239;
645   if (block_count <= 0 || block_count > DBG_MAX_COUNT)
646     {
647       LOG_ERROR ("Invalid r2007 system page: size_comp: %" PRId64
648                  ", size_uncomp: %" PRId64, size_comp, size_uncomp);
649       return NULL;
650     }
651   // Multiply with codeword size (255) and round to a multiple of 8
652   page_size = (block_count * 255 + 7) & ~7;
653   if ((uint64_t)page_size >= DBG_MAX_COUNT || (unsigned long)page_size > dat->size - dat->byte)
654     {
655       LOG_ERROR ("Invalid r2007 system page: page_size: %" PRId64, page_size);
656       return NULL;
657     }
658   assert ((uint64_t)size_comp < dat->size);
659   assert ((uint64_t)size_uncomp < dat->size);
660   assert ((uint64_t)repeat_count < DBG_MAX_COUNT);
661   assert ((uint64_t)page_size < DBG_MAX_COUNT);
662   data = (BITCODE_RC *)calloc (size_uncomp + page_size, 1);
663   LOG_HANDLE ("Alloc system page of size %" PRId64 "\n", size_uncomp + page_size)
664   if (!data)
665     {
666       LOG_ERROR ("Out of memory")
667       return NULL;
668     }
669 
670   rsdata = &data[size_uncomp];
671   bit_read_fixed (dat, rsdata, page_size);
672   pedata_size = block_count * 239;
673   pedata = decode_rs (rsdata, block_count, 239, page_size);
674   if (!pedata)
675     {
676       free (data);
677       return NULL;
678     }
679 
680   if (size_comp < size_uncomp)
681     error = decompress_r2007 (data, size_uncomp, pedata, MIN (pedata_size, size_comp));
682   else
683     memcpy (data, pedata, size_uncomp);
684 
685   free (pedata);
686   if (error >= DWG_ERR_CRITICAL)
687     {
688       free (data);
689       return NULL;
690     }
691   return data;
692 }
693 
694 static int
read_data_page(Bit_Chain * restrict dat,BITCODE_RC * restrict decomp,int64_t page_size,int64_t size_comp,int64_t size_uncomp)695 read_data_page (Bit_Chain *restrict dat, BITCODE_RC *restrict decomp,
696                 int64_t page_size, int64_t size_comp, int64_t size_uncomp)
697 {
698   int i;
699   int error = 0;
700 
701   int64_t pesize;      // Pre RS encoded size
702   int64_t block_count; // Number of RS encoded blocks
703 
704   BITCODE_RC *rsdata; // RS encoded data
705   BITCODE_RC *pedata; // Pre RS encoded data
706   long pedata_size;
707 
708   // Round to a multiple of 8
709   pesize = ((size_comp + 7) & ~7);
710   block_count = (pesize + 0xFB - 1) / 0xFB;
711   pedata_size = block_count * 0xFB;
712 
713   rsdata = (BITCODE_RC *)calloc (1, page_size);
714   if (rsdata == NULL)
715     {
716       LOG_ERROR ("Out of memory")
717       return DWG_ERR_OUTOFMEM;
718     }
719   bit_read_fixed (dat, rsdata, page_size);
720   pedata = decode_rs (rsdata, block_count, 0xFB, page_size);
721   if (!pedata)
722     {
723       free (rsdata);
724       return DWG_ERR_OUTOFMEM;
725     }
726 
727   if (size_comp < size_uncomp)
728     error = decompress_r2007 (decomp, size_uncomp, pedata,
729                               MIN (pedata_size, size_comp));
730   else
731     memcpy (decomp, pedata, size_uncomp);
732 
733   free (pedata);
734   free (rsdata);
735 
736   return error;
737 }
738 
739 static int
read_data_section(Bit_Chain * sec_dat,Bit_Chain * dat,r2007_section * restrict sections_map,r2007_page * restrict pages_map,Dwg_Section_Type sec_type)740 read_data_section (Bit_Chain *sec_dat, Bit_Chain *dat,
741                    r2007_section *restrict sections_map,
742                    r2007_page *restrict pages_map, Dwg_Section_Type sec_type)
743 {
744   r2007_section *section;
745   r2007_page *page;
746   uint64_t max_decomp_size;
747   BITCODE_RC *decomp;
748   int error = 0, i;
749 
750   section = get_section (sections_map, sec_type);
751   sec_dat->chain = NULL;
752   if (section == NULL)
753     {
754       if (sec_type < SECTION_REVHISTORY
755           && sec_type != SECTION_TEMPLATE
756           && sec_type != SECTION_OBJFREESPACE)
757         {
758           LOG_WARN ("Failed to find section_info[%u]", (int)sec_type)
759           return DWG_ERR_SECTIONNOTFOUND;
760         }
761       else
762         {
763           LOG_TRACE ("Found no section_info[%u]\n", (int)sec_type)
764           return DWG_ERR_VALUEOUTOFBOUNDS;
765         }
766     }
767 
768   max_decomp_size = section->data_size;
769   if (max_decomp_size > 0x2f000000) // 790Mb
770     {
771       LOG_ERROR ("Invalid max decompression size %" PRIu64, max_decomp_size);
772       return DWG_ERR_INVALIDDWG;
773     }
774   decomp = (BITCODE_RC *)calloc (max_decomp_size, 1);
775   if (decomp == NULL)
776     {
777       LOG_ERROR ("Out of memory")
778       return DWG_ERR_OUTOFMEM;
779     }
780   LOG_HANDLE ("Alloc data section of size %" PRIu64 "\n", max_decomp_size)
781 
782   sec_dat->bit = 0;
783   sec_dat->byte = 0;
784   sec_dat->size = max_decomp_size;
785   sec_dat->version = dat->version;
786   sec_dat->from_version = dat->from_version;
787 
788   for (i = 0; i < (int)section->num_pages; i++)
789     {
790       r2007_section_page *section_page = section->pages[i];
791       page = get_page (pages_map, section_page->id);
792       if (page == NULL)
793         {
794           free (decomp);
795           LOG_ERROR ("Failed to find page %d", (int)section_page->id)
796           return DWG_ERR_PAGENOTFOUND;
797         }
798       if (section_page->offset > max_decomp_size)
799         {
800           free (decomp);
801           LOG_ERROR ("Invalid section_page->offset %ld > %ld",
802                      (long)section_page->offset, (long)max_decomp_size)
803           return DWG_ERR_VALUEOUTOFBOUNDS;
804         }
805 
806       dat->byte = page->offset;
807       // only if compressed. TODO: Isn't there a compressed flag as with 2004+?
808       // theoretically the sizes could still be the same.
809       if (section_page->comp_size != section_page->uncomp_size)
810         {
811           error = read_data_page (dat, &decomp[section_page->offset],
812                                   page->size, section_page->comp_size,
813                                   section_page->uncomp_size);
814           if (error)
815             {
816               free (decomp);
817               LOG_ERROR ("Failed to read compressed page")
818               return error;
819             }
820         }
821       else
822         {
823           memcpy (&decomp[section_page->offset], &dat->chain[dat->byte],
824                   section_page->uncomp_size);
825         }
826     }
827   sec_dat->chain = decomp;
828   return 0;
829 }
830 
831 /* endian specific code: */
832 #define bfr_read_int16(_p)                                                    \
833   *((int16_t *)_p);                                                           \
834   _p += 2;
835 #define bfr_read_int64(_p)                                                    \
836   *((int64_t *)_p);                                                           \
837   _p += 8;
838 #define bfr_read_uint64(_p)                                                   \
839   *((uint64_t *)_p);                                                          \
840   _p += 8;
841 
842 static DWGCHAR *
bfr_read_string(BITCODE_RC * restrict * restrict src,int64_t size)843 bfr_read_string (BITCODE_RC *restrict *restrict src, int64_t size)
844 {
845   uint16_t *ptr = (uint16_t *)*src;
846   int32_t length = 0, wsize;
847   DWGCHAR *str, *str_base;
848   int i;
849 
850   if (size <= 0)
851     return NULL;
852   while (*ptr != 0 && length * 2 < size)
853     {
854       ptr++;
855       length++;
856     }
857 
858   wsize = length * sizeof (DWGCHAR) + sizeof (DWGCHAR);
859 
860   str = str_base = (DWGCHAR *)malloc (wsize);
861   if (!str)
862     {
863       LOG_ERROR ("Out of memory");
864       return NULL;
865     }
866   ptr = (uint16_t *)*src;
867   for (i = 0; i < length; i++)
868     {
869       *str++ = (DWGCHAR) (*ptr++);
870     }
871 
872   *src += size;
873   *str = 0;
874 
875   return str_base;
876 }
877 
878 static r2007_section *
read_sections_map(Bit_Chain * dat,int64_t size_comp,int64_t size_uncomp,int64_t correction)879 read_sections_map (Bit_Chain *dat, int64_t size_comp, int64_t size_uncomp,
880                    int64_t correction)
881 {
882   BITCODE_RC *data;
883   r2007_section *sections = NULL, *last_section = NULL, *section = NULL;
884   BITCODE_RC *ptr, *ptr_end;
885   int i, j = 0;
886 
887   data = read_system_page (dat, size_comp, size_uncomp, correction);
888   if (!data)
889     {
890       LOG_ERROR ("Failed to read system page")
891       return NULL;
892     }
893 
894   ptr = data;
895   ptr_end = data + size_uncomp;
896 
897   LOG_TRACE ("\n=== System Section (Section Map) ===\n")
898 
899   while (ptr < ptr_end)
900     {
901       section = (r2007_section *)calloc (1, sizeof (r2007_section));
902       if (!section)
903         {
904           LOG_ERROR ("Out of memory");
905           free (data);
906           sections_destroy (sections); // the root
907           return NULL;
908         }
909 
910       bfr_read (section, &ptr, 64);
911 
912       LOG_TRACE ("\nSection [%d]:\n", j)
913       LOG_TRACE ("  data size:     %" PRIu64 "\n", section->data_size)
914       LOG_TRACE ("  max size:      %" PRIu64 "\n", section->max_size)
915       LOG_TRACE ("  encryption:    %" PRIu64 "\n", section->encrypted)
916       LOG_HANDLE ("  hashcode:      %" PRIx64 "\n", section->hashcode)
917       LOG_HANDLE ("  name length:   %" PRIu64 "\n", section->name_length)
918       LOG_TRACE ("  unknown:       %" PRIu64 "\n", section->unknown)
919       LOG_TRACE ("  encoding:      %" PRIu64 "\n", section->encoded)
920       LOG_TRACE ("  num pages:     %" PRIu64 "\n", section->num_pages);
921 
922       // debugging sanity
923 #if 1
924       /* compressed */
925       if (section->data_size > 10 * dat->size
926           || section->name_length >= (int64_t)dat->size)
927         {
928           LOG_ERROR ("Invalid System Section");
929           free (section);
930           free (data);
931           sections_destroy (sections); // the root
932           return NULL;
933         }
934         // assert(section->data_size < dat->size + 0x100000);
935         // assert(section->max_size  < dat->size + 0x100000);
936         // assert(section->num_pages < DBG_MAX_COUNT);
937 #endif
938       // section->next = NULL;
939       // section->pages = NULL;
940       // section->name = NULL;
941 
942       if (!sections)
943         {
944           sections = last_section = section;
945         }
946       else
947         {
948           last_section->next = section;
949           last_section = section;
950         }
951 
952       j++;
953       if (ptr >= ptr_end)
954         break;
955 
956       // Section Name (wchar)
957       section->name = bfr_read_string (&ptr, section->name_length);
958 #ifdef HAVE_NATIVE_WCHAR2
959       LOG_TRACE ("  name:          " FORMAT_TU "\n\n",
960                  (BITCODE_TU)section->name)
961 #else
962       LOG_TRACE ("  name:          ")
963       LOG_TEXT_UNICODE (TRACE, section->name)
964       LOG_TRACE ("\n\n")
965 #endif
966       section->type = dwg_section_wtype (section->name);
967 
968       if (section->num_pages <= 0)
969         continue;
970       if (section->num_pages > 0xf0000)
971         {
972           LOG_ERROR ("Invalid num_pages %lu, skip", (unsigned long)section->num_pages);
973           continue;
974         }
975 
976       section->pages = (r2007_section_page **)calloc (
977           (size_t)section->num_pages, sizeof (r2007_section_page *));
978       if (!section->pages)
979         {
980           LOG_ERROR ("Out of memory");
981           free (data);
982           if (sections)
983             sections_destroy (sections); // the root
984           else
985             sections_destroy (section);
986           return NULL;
987         }
988 
989       for (i = 0; i < section->num_pages; i++)
990         {
991           section->pages[i]
992               = (r2007_section_page *)calloc (1, sizeof (r2007_section_page));
993           if (!section->pages[i])
994             {
995               LOG_ERROR ("Out of memory");
996               free (data);
997               if (sections)
998                 sections_destroy (sections); // the root
999               else
1000                 sections_destroy (section);
1001               return NULL;
1002             }
1003 
1004           if (ptr + 56 >= ptr_end)
1005             {
1006               LOG_ERROR ("Section[%d]->pages[%d] overflow", j, i);
1007               free (section->pages[i]);
1008               section->num_pages = i; // skip this last section
1009               break;
1010             }
1011           bfr_read (section->pages[i], &ptr, 56);
1012 
1013           LOG_TRACE (" Page[%d]: ", i)
1014           LOG_TRACE (" offset: 0x%07" PRIx64, section->pages[i]->offset);
1015           LOG_TRACE (" size: %5" PRIu64, section->pages[i]->size);
1016           LOG_TRACE (" id: %4" PRIu64, section->pages[i]->id);
1017           LOG_TRACE (" uncomp_size: %5" PRIu64 "\n",
1018                      section->pages[i]->uncomp_size);
1019           LOG_HANDLE (" comp_size: %5" PRIu64, section->pages[i]->comp_size);
1020           LOG_HANDLE (" checksum: %016" PRIx64, section->pages[i]->checksum);
1021           LOG_HANDLE (" crc64: %016" PRIx64 "\n", section->pages[i]->crc);
1022           // debugging sanity
1023           if (section->pages[i]->size >= DBG_MAX_SIZE
1024               || section->pages[i]->uncomp_size >= DBG_MAX_SIZE
1025               || section->pages[i]->comp_size >= DBG_MAX_SIZE)
1026             {
1027               LOG_ERROR ("Invalid section->pages[%d] size", i);
1028               free (data);
1029               free (section->pages[i]);
1030               section->num_pages = i; // skip this last section
1031               return sections;
1032             }
1033           assert (section->pages[i]->size < DBG_MAX_SIZE);
1034           assert (section->pages[i]->uncomp_size < DBG_MAX_SIZE);
1035           assert (section->pages[i]->comp_size < DBG_MAX_SIZE);
1036         }
1037     }
1038 
1039   free (data);
1040   return sections;
1041 }
1042 
1043 static r2007_page *
read_pages_map(Bit_Chain * dat,int64_t size_comp,int64_t size_uncomp,int64_t correction)1044 read_pages_map (Bit_Chain *dat, int64_t size_comp, int64_t size_uncomp,
1045                 int64_t correction)
1046 {
1047   BITCODE_RC *data, *ptr, *ptr_end;
1048   r2007_page *pages = NULL, *last_page = NULL, *page;
1049   int64_t offset = 0x480; // dat->byte;
1050   // int64_t index;
1051 
1052   data = read_system_page (dat, size_comp, size_uncomp, correction);
1053   if (!data)
1054     {
1055       LOG_ERROR ("Failed to read system page")
1056       return NULL;
1057     }
1058 
1059   ptr = data;
1060   ptr_end = data + size_uncomp;
1061 
1062   LOG_TRACE ("\n=== System Section (Pages Map) ===\n")
1063 
1064   while (ptr < ptr_end)
1065     {
1066       page = (r2007_page *)malloc (sizeof (r2007_page));
1067       if (page == NULL)
1068         {
1069           LOG_ERROR ("Out of memory")
1070           free (data);
1071           pages_destroy (pages);
1072           return NULL;
1073         }
1074       if (ptr + 16 > ptr_end)
1075         {
1076           LOG_ERROR ("Page out of bounds")
1077           free (data);
1078           pages_destroy (pages);
1079           return NULL;
1080         }
1081 
1082       page->size = bfr_read_uint64 (ptr);
1083       page->id = bfr_read_int64 (ptr);
1084       page->offset = offset;
1085       offset += page->size;
1086 
1087       // index = page->id > 0 ? page->id : -page->id;
1088 
1089       LOG_TRACE ("Page [%3" PRId64 "]: ", page->id)
1090       LOG_TRACE ("size: %6" PRIu64 " ", page->size)
1091       LOG_TRACE ("id: 0x%04" PRIx64 " ", page->id)
1092       LOG_TRACE ("offset: 0x%" PRIx64 " \n", page->offset)
1093 
1094       page->next = NULL;
1095 
1096       if (pages == NULL)
1097         pages = last_page = page;
1098       else
1099         {
1100           last_page->next = page;
1101           last_page = page;
1102         }
1103     }
1104   free (data);
1105   return pages;
1106 }
1107 
1108 /* Lookup a page in the page map. The page is identified by its id.
1109  */
1110 static r2007_page *
get_page(r2007_page * pages_map,int64_t id)1111 get_page (r2007_page *pages_map, int64_t id)
1112 {
1113   r2007_page *page = pages_map;
1114 
1115   while (page != NULL)
1116     {
1117       if (page->id == id)
1118         break;
1119       page = page->next;
1120     }
1121 
1122   return page;
1123 }
1124 
1125 static void
pages_destroy(r2007_page * page)1126 pages_destroy (r2007_page *page)
1127 {
1128   r2007_page *next;
1129 
1130   while (page != 0)
1131     {
1132       next = page->next;
1133       free (page);
1134       page = next;
1135     }
1136 }
1137 
1138 /* Lookup a section in the section map.
1139  * The section is identified by its numeric type.
1140  */
1141 static r2007_section *
get_section(r2007_section * sections_map,Dwg_Section_Type sec_type)1142 get_section (r2007_section *sections_map, Dwg_Section_Type sec_type)
1143 {
1144   r2007_section *section = sections_map;
1145   while (section != NULL)
1146     {
1147       if (section->type == sec_type)
1148         break;
1149       section = section->next;
1150     }
1151 
1152   return section;
1153 }
1154 
1155 static void
sections_destroy(r2007_section * section)1156 sections_destroy (r2007_section *section)
1157 {
1158   r2007_section *next;
1159 
1160   while (section != 0)
1161     {
1162       next = section->next;
1163 
1164       if (section->pages)
1165         {
1166           while (section->num_pages-- > 0)
1167             {
1168               free (section->pages[section->num_pages]);
1169             }
1170           free (section->pages);
1171         }
1172 
1173       if (section->name)
1174         free (section->name);
1175 
1176       free (section);
1177       section = next;
1178     }
1179 }
1180 
1181 static int
read_file_header(Bit_Chain * restrict dat,r2007_file_header * restrict file_header)1182 read_file_header (Bit_Chain *restrict dat,
1183                   r2007_file_header *restrict file_header)
1184 {
1185   BITCODE_RC data[0x3d8]; // 0x400 - 5 long
1186   BITCODE_RC *pedata;
1187   uint64_t seqence_crc;
1188   uint64_t seqence_key;
1189   uint64_t compr_crc;
1190   int32_t compr_len, len2;
1191   int i;
1192   int error = 0, errcount = 0;
1193   const int pedata_size = 3 * 239; // size of pedata
1194 
1195   dat->byte = 0x80;
1196   LOG_TRACE ("\n=== File header ===\n")
1197   memset (file_header, 0, sizeof (r2007_file_header));
1198   memset (data, 0, 0x3d8);
1199   bit_read_fixed (dat, data, 0x3d8);
1200   pedata = decode_rs (data, 3, 239, 0x3d8);
1201   if (!pedata)
1202     return DWG_ERR_OUTOFMEM;
1203 
1204   // Note: This is unportable to big-endian
1205   seqence_crc = *((uint64_t *)pedata);
1206   seqence_key = *((uint64_t *)&pedata[8]);
1207   compr_crc = *((uint64_t *)&pedata[16]);
1208   compr_len = *((int32_t *)&pedata[24]);
1209   len2 = *((int32_t *)&pedata[28]);
1210   LOG_TRACE ("seqence_crc64: %016lX\n", (unsigned long)seqence_crc);
1211   LOG_TRACE ("seqence_key:   %016lX\n", (unsigned long)seqence_key);
1212   LOG_TRACE ("compr_crc64:   %016lX\n", (unsigned long)compr_crc);
1213   LOG_TRACE ("compr_len:     %d\n", (int)compr_len); // only this is used
1214   LOG_TRACE ("len2:          %d\n", (int)len2);      // 0 when compressed
1215 
1216   if (compr_len > 0)
1217     error = decompress_r2007 ((BITCODE_RC *)file_header, 0x110, &pedata[32],
1218                               MIN (compr_len, pedata_size - 32));
1219   else
1220     memcpy (file_header, &pedata[32], sizeof (r2007_file_header));
1221 
1222   // check validity, for debugging only
1223   if (!error)
1224     {
1225 
1226 #define VALID_SIZE(var)                                                       \
1227   if (var < 0 || (unsigned)var > dat->size)                                   \
1228     {                                                                         \
1229       errcount++;                                                             \
1230       error |= DWG_ERR_VALUEOUTOFBOUNDS;                                      \
1231       LOG_ERROR ("%s Invalid %s %ld > MAX_SIZE", __FUNCTION__, #var,          \
1232                  (long)var)                                                   \
1233       var = 0;                                                                \
1234     }
1235 #define VALID_COUNT(var)                                                      \
1236   if (var < 0 || (unsigned)var > dat->size)                                   \
1237     {                                                                         \
1238       errcount++;                                                             \
1239       error |= DWG_ERR_VALUEOUTOFBOUNDS;                                      \
1240       LOG_ERROR ("%s Invalid %s %ld > MAX_COUNT", __FUNCTION__, #var,         \
1241                  (long)var)                                                   \
1242       var = 0;                                                                \
1243     }
1244 
1245       VALID_SIZE (file_header->header_size);
1246       VALID_SIZE (file_header->file_size);
1247       VALID_SIZE (file_header->pages_map_offset);
1248       VALID_SIZE (file_header->header2_offset);
1249       VALID_SIZE (file_header->pages_map_offset);
1250       VALID_SIZE (file_header->pages_map_size_comp);
1251       VALID_SIZE (file_header->pages_map_size_uncomp);
1252       VALID_COUNT (file_header->pages_maxid);
1253       VALID_COUNT (file_header->pages_amount);
1254       VALID_COUNT (file_header->num_sections);
1255     }
1256 
1257   free (pedata);
1258   return error;
1259 }
1260 
1261 /* Return the latest dat position for all three independent streams
1262    data, handle and string.
1263 */
1264 unsigned long
obj_stream_position(Bit_Chain * restrict dat,Bit_Chain * restrict hdl_dat,Bit_Chain * restrict str_dat)1265 obj_stream_position (Bit_Chain *restrict dat, Bit_Chain *restrict hdl_dat,
1266                      Bit_Chain *restrict str_dat)
1267 {
1268   unsigned long p1 = bit_position (dat);
1269   /* all 3 now relative to obj */
1270   unsigned long p2 = bit_position (hdl_dat);
1271   SINCE (R_2007)
1272     { // but only since 2007 there is a seperate string stream
1273       unsigned long p3 = bit_position (str_dat);
1274       if (p2 > p1)
1275         return p3 > p2 ? p3 : p2;
1276       else
1277         return p3 > p1 ? p3 : p1;
1278     }
1279   else
1280     {
1281       return (p2 > p1) ? p2 : p1;
1282     }
1283 }
1284 
1285 int
obj_string_stream(Bit_Chain * restrict dat,Dwg_Object * restrict obj,Bit_Chain * restrict str)1286 obj_string_stream (Bit_Chain *restrict dat, Dwg_Object *restrict obj,
1287                    Bit_Chain *restrict str)
1288 {
1289   BITCODE_RL start = obj->bitsize - 1; // in bits
1290   BITCODE_RL data_size = 0;            // in byte
1291   BITCODE_RL old_size;                 // in byte
1292   BITCODE_RL old_byte;
1293   //assert (dat != str); // r2007 objects are the same, just entities not
1294   old_size = str->size;
1295   old_byte = str->byte;
1296 
1297   //str->chain += str->byte;
1298   //obj->strpos = str->byte * 8 + str->bit;
1299 
1300   str->size = (obj->bitsize / 8) + ((obj->bitsize % 8) ? 1 : 0);
1301   bit_set_position (str, start);
1302 
1303   if (str->byte >= old_size - old_byte)
1304     {
1305       LOG_ERROR ("obj_string_stream overflow, bitsize " FORMAT_RL " => " FORMAT_RL,
1306                  obj->bitsize, obj->size * 8);
1307       str->byte = old_byte;
1308       str->size = old_size;
1309       obj->has_strings = 0;
1310       obj->bitsize = obj->size * 8;
1311       return DWG_ERR_VALUEOUTOFBOUNDS;
1312     }
1313   LOG_HANDLE (" obj string stream +%u: @%lu.%u (%lu)", start, str->byte,
1314               str->bit & 7, bit_position (str));
1315   obj->has_strings = bit_read_B (str);
1316   LOG_TRACE (" has_strings: %d\n", (int)obj->has_strings);
1317   if (!obj->has_strings)
1318     {
1319       // FIXME wrong bit
1320       if (obj->fixedtype == DWG_TYPE_SCALE)
1321         obj->has_strings = 1;
1322       // str->size = 0;
1323       // bit_reset_chain (str);
1324       return 0;
1325     }
1326 
1327   bit_advance_position (str, -1); //-17
1328   str->byte -= 2;
1329   LOG_HANDLE (" @%lu.%u", str->byte, str->bit & 7);
1330   data_size = (BITCODE_RL)bit_read_RS (str);
1331   LOG_HANDLE (" data_size: %u/0x%x [RS]", data_size, data_size);
1332 
1333   if (data_size & 0x8000)
1334     {
1335       BITCODE_RS hi_size;
1336       str->byte -= 4;
1337       data_size &= 0x7FFF;
1338       LOG_HANDLE (" @%lu.%u", str->byte, str->bit & 7);
1339       hi_size = bit_read_RS (str);
1340       LOG_HANDLE (" hi_size " FORMAT_RS "/" FORMAT_RSx " [RS]", hi_size, hi_size);
1341       data_size |= (hi_size << 15);
1342       LOG_HANDLE (" => data_size: %u/0x%x\n", data_size, data_size);
1343       // LOG_TRACE("  -33: @%lu\n", str->byte);
1344     }
1345   else
1346     LOG_HANDLE ("\n");
1347   str->byte -= 2;
1348   if (data_size > obj->bitsize)
1349     {
1350       LOG_WARN ("Invalid string stream data_size %u > bitsize %u at @%lu.%u\n",
1351                 (unsigned)data_size, (unsigned)obj->bitsize, str->byte, str->bit & 7);
1352       if (dat->from_version == R_2007)
1353         {
1354           return 0;
1355         }
1356       obj->has_strings = 0;
1357       bit_reset_chain (str);
1358       return DWG_ERR_NOTYETSUPPORTED; // a very low severity error
1359     }
1360   if (data_size < obj->bitsize)
1361     {
1362       obj->stringstream_size = data_size;
1363       bit_advance_position (str, -(int)data_size);
1364     }
1365   else
1366     {
1367       bit_set_position (str, 0);
1368     }
1369   // bit_reset_chain (str);
1370   // LOG_TRACE(" %d: @%lu.%u (%lu)\n", -(int)data_size - 16, str->byte,
1371   // str->bit & 7,
1372   //          bit_position(str));
1373   // obj->strpos = obj->bitsize_pos + obj->bitsize - obj->stringstream_size;
1374   return 0;
1375 }
1376 
1377 void
section_string_stream(Dwg_Data * restrict dwg,Bit_Chain * restrict dat,BITCODE_RL bitsize,Bit_Chain * restrict str)1378 section_string_stream (Dwg_Data *restrict dwg, Bit_Chain *restrict dat, BITCODE_RL bitsize,
1379                        Bit_Chain *restrict str)
1380 {
1381   BITCODE_RL start;     // in bits
1382   BITCODE_RL data_size; // in bits
1383   BITCODE_B endbit;
1384   if (dwg->header.version < R_2010 ||
1385       (dwg->header.version == R_2010 && dwg->header.maint_version < 3))
1386   {
1387     // r2007: + 24 bytes (sentinel+size+hsize) - 1 bit (endbit)
1388     start = bitsize + 159;
1389   }
1390   else
1391   {
1392     // r2010: + 24 bytes (sentinel+size+hSize) - 1 bit (endbit)
1393     start = bitsize + 191; /* 8*24 = 192 */
1394   }
1395   *str = *dat;
1396   bit_set_position (str, start);
1397   LOG_TRACE ("section string stream\n  pos: " FORMAT_RL ", %lu/%u\n", start,
1398              str->byte, str->bit);
1399   endbit = bit_read_B (str);
1400   LOG_HANDLE ("  endbit: %d\n", (int)endbit);
1401   if (!endbit)
1402     return; // i.e. has no strings. without data_size should be 0
1403   start -= 16;
1404   bit_set_position (str, start);
1405   LOG_HANDLE ("  pos: " FORMAT_RL ", %lu\n", start, str->byte);
1406   // str->bit = start & 7;
1407   data_size = bit_read_RS (str);
1408   LOG_HANDLE ("  data_size: " FORMAT_RL "\n", data_size);
1409   if (data_size & 0x8000)
1410     {
1411       BITCODE_RS hi_size;
1412       start -= 16;
1413       data_size &= 0x7FFF;
1414       bit_set_position (str, start);
1415       LOG_HANDLE ("  pos: " FORMAT_RL ", %lu\n", start, str->byte);
1416       hi_size = bit_read_RS (str);
1417       data_size |= (hi_size << 15);
1418       LOG_HANDLE ("  hi_size: " FORMAT_RS ", data_size: " FORMAT_RL "\n",
1419                   hi_size, data_size);
1420     }
1421   start -= data_size;
1422   bit_set_position (str, start);
1423   LOG_HANDLE ("  pos: " FORMAT_RL ", %lu/%u\n", start, str->byte, str->bit);
1424 }
1425 
1426 // for string stream see p86
1427 static int
read_2007_section_classes(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1428 read_2007_section_classes (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
1429                            r2007_section *restrict sections_map,
1430                            r2007_page *restrict pages_map)
1431 {
1432   BITCODE_RL size, i;
1433   BITCODE_BS max_num;
1434   Bit_Chain sec_dat = { 0 }, str = { 0 };
1435   Dwg_Object *obj = NULL;
1436   int error;
1437   char c;
1438 
1439   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
1440                              SECTION_CLASSES);
1441   if (error)
1442     {
1443       LOG_ERROR ("Failed to read class section");
1444       if (sec_dat.chain)
1445         free (sec_dat.chain);
1446       return error;
1447     }
1448 
1449   if (bit_search_sentinel (&sec_dat, dwg_sentinel (DWG_SENTINEL_CLASS_BEGIN)))
1450     {
1451       BITCODE_RL bitsize = 0;
1452       LOG_TRACE ("\nClasses\n-------------------\n")
1453       size = bit_read_RL (&sec_dat); // size of class data area
1454       LOG_TRACE ("size: " FORMAT_RL " [RL]\n", size)
1455       /*
1456       if (dat->from_version >= R_2010 && dwg->header.maint_version > 3)
1457         {
1458           BITCODE_RL hsize = bit_read_RL(&sec_dat);
1459           LOG_TRACE("hsize: " FORMAT_RL " [RL]\n", hsize)
1460         }
1461       */
1462       if (dat->from_version >= R_2007)
1463         {
1464           bitsize = bit_read_RL (&sec_dat);
1465           LOG_TRACE ("bitsize: " FORMAT_RL " [RL]\n", bitsize)
1466         }
1467       max_num = bit_read_BS (&sec_dat); // Maximum class number
1468       LOG_TRACE ("max_num: " FORMAT_BS " [BS]\n", max_num)
1469       c = bit_read_RC (&sec_dat); // 0x00
1470       LOG_HANDLE ("c: " FORMAT_RC " [RC]\n", c)
1471       c = bit_read_RC (&sec_dat); // 0x00
1472       LOG_HANDLE ("c: " FORMAT_RC " [RC]\n", c)
1473       c = bit_read_B (&sec_dat); // 1
1474       LOG_HANDLE ("c: " FORMAT_B " [B]\n", c);
1475 
1476       dwg->layout_type = 0;
1477       dwg->num_classes = max_num - 499;
1478       if (max_num < 500 || max_num > 5000)
1479         {
1480           LOG_ERROR ("Invalid max class number %d", max_num)
1481           dwg->num_classes = 0;
1482           if (sec_dat.chain)
1483             free (sec_dat.chain);
1484           return DWG_ERR_VALUEOUTOFBOUNDS;
1485         }
1486       assert (max_num >= 500);
1487       assert (max_num < 5000);
1488 
1489       section_string_stream (dwg, &sec_dat, bitsize, &str);
1490 
1491       dwg->dwg_class
1492           = (Dwg_Class *)calloc (dwg->num_classes, sizeof (Dwg_Class));
1493       if (!dwg->dwg_class)
1494         {
1495           LOG_ERROR ("Out of memory");
1496           if (sec_dat.chain)
1497             free (sec_dat.chain);
1498           return DWG_ERR_OUTOFMEM;
1499         }
1500 
1501       for (i = 0; i < dwg->num_classes; i++)
1502         {
1503           dwg->dwg_class[i].number = bit_read_BS (&sec_dat);
1504           dwg->dwg_class[i].proxyflag = bit_read_BS (&sec_dat);
1505           dwg->dwg_class[i].appname = (char *)bit_read_TU (&str);
1506           dwg->dwg_class[i].cppname = (char *)bit_read_TU (&str);
1507           dwg->dwg_class[i].dxfname_u = bit_read_TU (&str);
1508           dwg->dwg_class[i].is_zombie = bit_read_B (&sec_dat); // DXF 280
1509           dwg->dwg_class[i].item_class_id = bit_read_BS (&sec_dat); // DXF 281, is_entity is 0x1f3
1510 
1511           dwg->dwg_class[i].num_instances = bit_read_BL (&sec_dat); // DXF 91
1512           dwg->dwg_class[i].dwg_version = bit_read_BS (&sec_dat);
1513           dwg->dwg_class[i].maint_version = bit_read_BS (&sec_dat);
1514           dwg->dwg_class[i].unknown_1 = bit_read_BL (&sec_dat); // 0
1515           dwg->dwg_class[i].unknown_2 = bit_read_BL (&sec_dat); // 0
1516 
1517           LOG_TRACE ("-------------------\n")
1518           LOG_TRACE ("Number:           %d\n", dwg->dwg_class[i].number)
1519           LOG_TRACE ("Proxyflag:        0x%x\n", dwg->dwg_class[i].proxyflag)
1520           LOG_TRACE_TU ("Application name", dwg->dwg_class[i].appname, 0)
1521           LOG_TRACE_TU ("C++ class name  ", dwg->dwg_class[i].cppname, 0)
1522           LOG_TRACE_TU ("DXF record name ", dwg->dwg_class[i].dxfname_u, 0)
1523           LOG_TRACE ("Class ID:         0x%x "
1524                      "(0x1f3 for object, 0x1f2 for entity)\n",
1525                      dwg->dwg_class[i].item_class_id)
1526           LOG_TRACE ("instance count:   %u\n", dwg->dwg_class[i].num_instances)
1527           LOG_TRACE ("dwg version:      %u (%u)\n",
1528                      dwg->dwg_class[i].dwg_version,
1529                      dwg->dwg_class[i].maint_version)
1530           LOG_HANDLE ("unknown:          %u %u\n", dwg->dwg_class[i].unknown_1,
1531                       dwg->dwg_class[i].unknown_2)
1532 
1533           dwg->dwg_class[i].dxfname
1534               = bit_convert_TU (dwg->dwg_class[i].dxfname_u);
1535           if (dwg->dwg_class[i].dxfname
1536               && strEQc (dwg->dwg_class[i].dxfname, "LAYOUT"))
1537             dwg->layout_type = dwg->dwg_class[i].number;
1538         }
1539     }
1540   else
1541     {
1542       LOG_ERROR ("Failed to find class section sentinel");
1543       free (sec_dat.chain);
1544       return DWG_ERR_CLASSESNOTFOUND;
1545     }
1546 
1547   if (sec_dat.chain)
1548     free (sec_dat.chain);
1549 
1550   return 0;
1551 }
1552 
1553 static int
read_2007_section_header(Bit_Chain * restrict dat,Bit_Chain * restrict hdl_dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1554 read_2007_section_header (Bit_Chain *restrict dat, Bit_Chain *restrict hdl_dat,
1555                           Dwg_Data *restrict dwg,
1556                           r2007_section *restrict sections_map,
1557                           r2007_page *restrict pages_map)
1558 {
1559   Bit_Chain sec_dat = { 0 }, str_dat = { 0 };
1560   int error;
1561   LOG_TRACE ("\nSection Header\n-------------------\n");
1562   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
1563                              SECTION_HEADER);
1564   if (error)
1565     {
1566       LOG_ERROR ("Failed to read header section");
1567       if (sec_dat.chain)
1568         free (sec_dat.chain);
1569       return error;
1570     }
1571   if (bit_search_sentinel (&sec_dat,
1572                            dwg_sentinel (DWG_SENTINEL_VARIABLE_BEGIN)))
1573     {
1574       BITCODE_RL endbits = 160; // start bit: 16 sentinel + 4 size
1575       dwg->header_vars.size = bit_read_RL (&sec_dat);
1576       LOG_TRACE ("size: " FORMAT_RL "\n", dwg->header_vars.size);
1577       *hdl_dat = sec_dat;
1578       // unused: later versions re-use the 2004 section format
1579       /*
1580       if (dat->from_version >= R_2010 && dwg->header.maint_version > 3)
1581         {
1582           dwg->header_vars.bitsize_hi = bit_read_RL(&sec_dat);
1583           LOG_TRACE("bitsize_hi: " FORMAT_RL " [RL]\n",
1584       dwg->header_vars.bitsize_hi) endbits += 32;
1585         }
1586       */
1587       if (dat->from_version == R_2007) // always true so far
1588         {
1589           dwg->header_vars.bitsize = bit_read_RL (&sec_dat);
1590           LOG_TRACE ("bitsize: " FORMAT_RL " [RL]\n",
1591                      dwg->header_vars.bitsize);
1592           endbits += dwg->header_vars.bitsize;
1593           bit_set_position (hdl_dat, endbits);
1594           section_string_stream (dwg, &sec_dat, dwg->header_vars.bitsize, &str_dat);
1595         }
1596 
1597       dwg_decode_header_variables (&sec_dat, hdl_dat, &str_dat, dwg);
1598     }
1599   else
1600     {
1601       DEBUG_HERE;
1602       error = DWG_ERR_SECTIONNOTFOUND;
1603     }
1604 
1605   if (sec_dat.chain)
1606     free (sec_dat.chain);
1607 
1608   return error;
1609 }
1610 
1611 static int
read_2007_section_handles(Bit_Chain * dat,Bit_Chain * hdl,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1612 read_2007_section_handles (Bit_Chain *dat, Bit_Chain *hdl,
1613                            Dwg_Data *restrict dwg,
1614                            r2007_section *restrict sections_map,
1615                            r2007_page *restrict pages_map)
1616 {
1617   static Bit_Chain obj_dat = { 0 }, hdl_dat = { 0 };
1618   BITCODE_RS section_size = 0;
1619   long unsigned int endpos;
1620   int error;
1621 
1622   error = read_data_section (&obj_dat, dat, sections_map, pages_map,
1623                              SECTION_OBJECTS);
1624   if (error >= DWG_ERR_CRITICAL || !obj_dat.chain)
1625     {
1626       LOG_ERROR ("Failed to read objects section");
1627       if (obj_dat.chain)
1628         free (obj_dat.chain);
1629       return error;
1630     }
1631 
1632   LOG_TRACE ("\nHandles\n-------------------\n")
1633   error = read_data_section (&hdl_dat, dat, sections_map, pages_map,
1634                              SECTION_HANDLES);
1635   if (error >= DWG_ERR_CRITICAL|| !hdl_dat.chain)
1636     {
1637       LOG_ERROR ("Failed to read handles section");
1638       if (obj_dat.chain)
1639         free (obj_dat.chain);
1640       if (hdl_dat.chain)
1641         free (hdl_dat.chain);
1642       return error;
1643     }
1644 
1645   /* From here on the same code as in decode:read_2004_section_handles */
1646   endpos = hdl_dat.byte + hdl_dat.size;
1647   dwg->num_objects = 0;
1648 
1649   do
1650     {
1651       long unsigned int last_offset;
1652       // long unsigned int last_handle;
1653       long unsigned int oldpos = 0;
1654       long unsigned int startpos = hdl_dat.byte;
1655       uint16_t crc1, crc2;
1656 
1657       section_size = bit_read_RS_LE (&hdl_dat);
1658       LOG_TRACE ("\nSection size: %u\n", section_size);
1659       if (section_size > 2050)
1660         {
1661           LOG_ERROR ("Object-map/handles section size greater than 2050!");
1662           return DWG_ERR_VALUEOUTOFBOUNDS;
1663         }
1664 
1665       last_offset = 0;
1666       while ((long)(hdl_dat.byte - startpos) < (long)section_size)
1667         {
1668           int added;
1669           BITCODE_UMC handleoff;
1670           BITCODE_MC offset;
1671 
1672           oldpos = hdl_dat.byte;
1673           handleoff = bit_read_UMC (&hdl_dat);
1674           offset = bit_read_MC (&hdl_dat);
1675           last_offset += offset;
1676           LOG_TRACE ("\nNext object: %lu ", (unsigned long)dwg->num_objects)
1677           LOG_TRACE ("Handleoff: " FORMAT_MC " [UMC] "
1678                      "Offset: " FORMAT_MC " [MC] @%lu\n",
1679                      handleoff, offset, last_offset)
1680 
1681           if (hdl_dat.byte == oldpos)
1682             break;
1683 
1684           added = dwg_decode_add_object (dwg, &obj_dat, hdl, last_offset);
1685           if (added > 0)
1686             error |= added;
1687         }
1688 
1689       if (hdl_dat.byte == oldpos)
1690         break;
1691 #if 0
1692       if (!bit_check_CRC(&hdl_dat, startpos, 0xC0C1))
1693         LOG_WARN("Handles section CRC mismatch at offset %lx", startpos);
1694 #else
1695       crc1 = bit_calc_CRC (0xC0C1, &(hdl_dat.chain[startpos]),
1696                            hdl_dat.byte - startpos);
1697       crc2 = bit_read_RS_LE (&hdl_dat);
1698       if (crc1 == crc2)
1699         {
1700           LOG_INSANE ("Handles section page CRC: %04X from %lx-%lx\n", crc2,
1701                       startpos, hdl_dat.byte - 2);
1702         }
1703       else
1704         {
1705           LOG_WARN ("Handles section page CRC mismatch: %04X vs calc. %04X "
1706                     "from %lx-%lx\n",
1707                     crc2, crc1, startpos, hdl_dat.byte - 2);
1708           error |= DWG_ERR_WRONGCRC;
1709         }
1710 #endif
1711 
1712       if (hdl_dat.byte >= endpos)
1713         break;
1714     }
1715   while (section_size > 2);
1716 
1717   if (hdl_dat.chain)
1718     free (hdl_dat.chain);
1719   if (obj_dat.chain)
1720     free (obj_dat.chain);
1721   return error;
1722 }
1723 
1724 /* VBAProject Section
1725  */
1726 static int
read_2007_section_vbaproject(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1727 read_2007_section_vbaproject (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
1728                               r2007_section *restrict sections_map,
1729                               r2007_page *restrict pages_map)
1730 {
1731   Bit_Chain old_dat, sec_dat = { 0 };
1732   //Bit_Chain *str_dat;
1733   Dwg_VBAProject *_obj = &dwg->vbaproject;
1734   Dwg_Object *obj = NULL;
1735   int error = 0;
1736   //BITCODE_RL rcount1 = 0, rcount2 = 0;
1737 
1738   // not compressed, page size: 0x80
1739   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
1740                              SECTION_VBAPROJECT);
1741   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
1742     {
1743       LOG_INFO ("%s section not found\n", "VBAProject");
1744       if (sec_dat.chain)
1745         free (sec_dat.chain);
1746       return error;
1747     }
1748 
1749   LOG_TRACE ("\nVBAProject (%lu)\n-------------------\n", sec_dat.size)
1750   old_dat = *dat;
1751   dat = &sec_dat; // restrict in size
1752   bit_chain_set_version (&old_dat, dat);
1753 
1754   DEBUG_HERE
1755   _obj->size = dat->size;
1756   _obj->unknown_bits = bit_read_TF (dat, _obj->size);
1757   LOG_TRACE_TF (_obj->unknown_bits, _obj->size)
1758 
1759   LOG_TRACE ("\n")
1760   if (sec_dat.chain)
1761     free (sec_dat.chain);
1762   *dat = old_dat; // unrestrict
1763   return error;
1764 }
1765 
1766 static int
read_2007_section_summary(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1767 read_2007_section_summary (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
1768                            r2007_section *restrict sections_map,
1769                            r2007_page *restrict pages_map)
1770 {
1771   static Bit_Chain old_dat, sec_dat = { 0 };
1772   Bit_Chain *str_dat;
1773   Dwg_SummaryInfo *_obj = &dwg->summaryinfo;
1774   Dwg_Object *obj = NULL;
1775   int error;
1776   BITCODE_RL rcount1 = 0, rcount2 = 0;
1777 
1778   old_dat = *dat;
1779   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
1780                              SECTION_SUMMARYINFO);
1781   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
1782     {
1783       LOG_ERROR ("Failed to read SummaryInfo section");
1784       if (sec_dat.chain)
1785         free (sec_dat.chain);
1786       return error;
1787     }
1788 
1789   if (dwg->header.summaryinfo_address != (BITCODE_RL)dat->byte)
1790     LOG_WARN ("summaryinfo_address mismatch: " FORMAT_RL " != %lu",
1791               dwg->header.summaryinfo_address, dat->byte);
1792   LOG_TRACE ("\nSummaryInfo (%lu)\n-------------------\n", sec_dat.size)
1793   str_dat = dat = &sec_dat; // restrict in size
1794   bit_chain_set_version (&old_dat, dat);
1795 
1796   // clang-format off
1797   #include "summaryinfo.spec"
1798   // clang-format on
1799 
1800   if (sec_dat.chain)
1801     free (sec_dat.chain);
1802   *dat = old_dat; // unrestrict
1803   return error;
1804 }
1805 
1806 /* AppInfo Section
1807  */
1808 static int
read_2007_section_appinfo(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1809 read_2007_section_appinfo (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
1810                            r2007_section *restrict sections_map,
1811                            r2007_page *restrict pages_map)
1812 {
1813   Bit_Chain old_dat, sec_dat = { 0 };
1814   Bit_Chain *str_dat;
1815   Dwg_AppInfo *_obj = &dwg->appinfo;
1816   Dwg_Object *obj = NULL;
1817   int error = 0;
1818   BITCODE_RL rcount1 = 0, rcount2 = 0;
1819 
1820   // not compressed, page size: 0x80
1821   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
1822                              SECTION_APPINFO);
1823   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
1824     {
1825       LOG_INFO ("%s section not found\n", "AppInfo");
1826       if (sec_dat.chain)
1827         free (sec_dat.chain);
1828       return error;
1829     }
1830 
1831   LOG_TRACE ("\nAppInfo (%lu)\n-------------------\n", sec_dat.size)
1832   old_dat = *dat;
1833   str_dat = dat = &sec_dat; // restrict in size
1834   bit_chain_set_version (&old_dat, dat);
1835 
1836   // clang-format off
1837   #include "appinfo.spec"
1838   // clang-format on
1839 
1840   LOG_TRACE ("\n")
1841   if (sec_dat.chain)
1842     free (sec_dat.chain);
1843   *dat = old_dat; // unrestrict
1844   return error;
1845 }
1846 
1847 /* AuxHeader Section
1848  */
1849 static int
read_2007_section_auxheader(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1850 read_2007_section_auxheader (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
1851                              r2007_section *restrict sections_map,
1852                              r2007_page *restrict pages_map)
1853 {
1854   Bit_Chain old_dat, sec_dat = { 0 };
1855   //Bit_Chain *str_dat;
1856   Dwg_AuxHeader *_obj = &dwg->auxheader;
1857   Dwg_Object *obj = NULL;
1858   int error = 0;
1859   BITCODE_RL vcount = 0, rcount1 = 0, rcount2 = 0;
1860 
1861   // type: 2, compressed, page size: 0x7400
1862   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
1863                              SECTION_AUXHEADER);
1864   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
1865     {
1866       LOG_INFO ("%s section not found\n", "AuxHeader");
1867       if (sec_dat.chain)
1868         free (sec_dat.chain);
1869       return error;
1870     }
1871 
1872   LOG_TRACE ("\nAuxHeader (%lu)\n-------------------\n", sec_dat.size)
1873   old_dat = *dat;
1874   dat = &sec_dat; // restrict in size
1875   bit_chain_set_version (&old_dat, dat);
1876 
1877   // clang-format off
1878   #include "auxheader.spec"
1879   // clang-format on
1880 
1881   LOG_TRACE ("\n")
1882   if (sec_dat.chain)
1883     free (sec_dat.chain);
1884   *dat = old_dat; // unrestrict
1885   return error;
1886 }
1887 
1888 /* Unknown AppInfoHistory Section
1889  */
1890 static int
read_2007_section_appinfohistory(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1891 read_2007_section_appinfohistory (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
1892                                   r2007_section *restrict sections_map,
1893                                   r2007_page *restrict pages_map)
1894 {
1895   Bit_Chain old_dat, sec_dat = { 0 };
1896   //Bit_Chain *str_dat;
1897   Dwg_AppInfoHistory *_obj = &dwg->appinfohistory;
1898   Dwg_Object *obj = NULL;
1899   int error = 0;
1900   //BITCODE_RL rcount1 = 0, rcount2 = 0;
1901 
1902   // compressed, page size: 0x580
1903   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
1904                              SECTION_APPINFOHISTORY);
1905   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
1906     {
1907       LOG_INFO ("%s section not found\n", "AppInfoHistory");
1908       if (sec_dat.chain)
1909         free (sec_dat.chain);
1910       return error;
1911     }
1912 
1913   LOG_TRACE ("\nAppInfoHistory (%lu)\n-------------------\n", sec_dat.size)
1914   old_dat = *dat;
1915   dat = &sec_dat; // restrict in size
1916   bit_chain_set_version (&old_dat, dat);
1917 
1918   DEBUG_HERE
1919   _obj->size = dat->size;
1920   _obj->unknown_bits = bit_read_TF (dat, _obj->size);
1921   LOG_TRACE_TF (_obj->unknown_bits, _obj->size)
1922 
1923   LOG_TRACE ("\n")
1924   if (sec_dat.chain)
1925     free (sec_dat.chain);
1926   *dat = old_dat; // unrestrict
1927   return error;
1928 }
1929 
1930 /* RevHistory Section
1931  */
1932 static int
read_2007_section_revhistory(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1933 read_2007_section_revhistory (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
1934                               r2007_section *restrict sections_map,
1935                               r2007_page *restrict pages_map)
1936 {
1937   Bit_Chain old_dat, sec_dat = { 0 };
1938   //Bit_Chain *str_dat;
1939   Dwg_RevHistory *_obj = &dwg->revhistory;
1940   Dwg_Object *obj = NULL;
1941   int error = 0;
1942   BITCODE_RL rcount1 = 0, rcount2 = 0;
1943 
1944   // compressed, page size: 0x7400
1945   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
1946                              SECTION_REVHISTORY);
1947   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
1948     {
1949       LOG_INFO ("%s section not found\n", "RevHistory");
1950       if (sec_dat.chain)
1951         free (sec_dat.chain);
1952       return error;
1953     }
1954 
1955   LOG_TRACE ("\nRevHistory (%lu)\n-------------------\n", sec_dat.size)
1956   old_dat = *dat;
1957   dat = &sec_dat; // restrict in size
1958   bit_chain_set_version (&old_dat, dat);
1959 
1960   // clang-format off
1961   #include "revhistory.spec"
1962   // clang-format on
1963 
1964   LOG_TRACE ("\n")
1965   if (sec_dat.chain)
1966     free (sec_dat.chain);
1967   *dat = old_dat; // unrestrict
1968   return error;
1969 }
1970 
1971 /* ObjFreeSpace Section
1972  */
1973 static int
read_2007_section_objfreespace(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)1974 read_2007_section_objfreespace (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
1975                                 r2007_section *restrict sections_map,
1976                                 r2007_page *restrict pages_map)
1977 {
1978   Bit_Chain old_dat, sec_dat = { 0 };
1979   //Bit_Chain *str_dat;
1980   Dwg_ObjFreeSpace *_obj = &dwg->objfreespace;
1981   Dwg_Object *obj = NULL;
1982   int error = 0;
1983   BITCODE_RL rcount1 = 0, rcount2 = 0;
1984 
1985   // compressed, page size: 0x7400
1986   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
1987                              SECTION_OBJFREESPACE);
1988   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
1989     {
1990       LOG_INFO ("%s section not found\n", "ObjFreeSpace");
1991       if (sec_dat.chain)
1992         free (sec_dat.chain);
1993       return error;
1994     }
1995 
1996   LOG_TRACE ("\nObjFreeSpace (%lu)\n-------------------\n", sec_dat.size)
1997   old_dat = *dat;
1998   dat = &sec_dat; // restrict in size
1999   bit_chain_set_version (&old_dat, dat);
2000 
2001   // clang-format off
2002   #include "objfreespace.spec"
2003   // clang-format on
2004 
2005   LOG_TRACE ("\n")
2006   if (sec_dat.chain)
2007     free (sec_dat.chain);
2008   *dat = old_dat; // unrestrict
2009   return error;
2010 }
2011 
2012 /* Template Section. Optional r13-r15, mandatory r18+.
2013    Contains the MEASUREMENT variable (0 = English, 1 = Metric).
2014  */
2015 static int
read_2007_section_template(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)2016 read_2007_section_template (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
2017                             r2007_section *restrict sections_map,
2018                             r2007_page *restrict pages_map)
2019 {
2020   Bit_Chain old_dat, sec_dat = { 0 };
2021   //Bit_Chain *str_dat;
2022   Dwg_Template *_obj = &dwg->Template;
2023   Dwg_Object *obj = NULL;
2024   int error = 0;
2025   BITCODE_RL rcount1 = 0, rcount2 = 0;
2026 
2027   // compressed
2028   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
2029                              SECTION_TEMPLATE);
2030   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
2031     {
2032       LOG_ERROR ("%s section not found\n", "Template");
2033       if (sec_dat.chain)
2034         free (sec_dat.chain);
2035       return error | DWG_ERR_SECTIONNOTFOUND;
2036     }
2037 
2038   LOG_TRACE ("\nTemplate (%lu)\n-------------------\n", sec_dat.size)
2039   old_dat = *dat;
2040   dat = &sec_dat; // restrict in size
2041   bit_chain_set_version (&old_dat, dat);
2042 
2043   // clang-format off
2044   #include "template.spec"
2045   // clang-format on
2046 
2047   dwg->header_vars.MEASUREMENT = _obj->MEASUREMENT;
2048   LOG_TRACE ("HEADER.MEASUREMENT: " FORMAT_BS " (0 English/1 Metric)\n",
2049              dwg->header_vars.MEASUREMENT)
2050 
2051   LOG_TRACE ("\n")
2052   if (sec_dat.chain)
2053     free (sec_dat.chain);
2054   *dat = old_dat; // unrestrict
2055   return error;
2056 }
2057 
2058 /* r21 FileDepList Section
2059  */
2060 static int
read_2007_section_filedeplist(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)2061 read_2007_section_filedeplist (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
2062                                r2007_section *restrict sections_map,
2063                                r2007_page *restrict pages_map)
2064 {
2065   Bit_Chain old_dat, sec_dat = { 0 };
2066   int error;
2067   Bit_Chain *str_dat;
2068   Dwg_FileDepList *_obj = &dwg->filedeplist;
2069   Dwg_Object *obj = NULL;
2070   BITCODE_BL vcount;
2071   BITCODE_RL rcount1 = 0, rcount2 = 0;
2072 
2073   // not compressed, page size: 0x80. 0xc or 0xd
2074   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
2075                              SECTION_FILEDEPLIST);
2076   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
2077     {
2078       LOG_INFO ("%s section not found\n", "FileDepList");
2079       if (sec_dat.chain)
2080         free (sec_dat.chain);
2081       return 0;
2082     }
2083 
2084   LOG_TRACE ("FileDepList (%lu)\n-------------------\n", sec_dat.size)
2085   old_dat = *dat;
2086   str_dat = dat = &sec_dat; // restrict in size
2087   bit_chain_set_version (&old_dat, dat);
2088 
2089   // clang-format off
2090   #include "filedeplist.spec"
2091   // clang-format on
2092 
2093   LOG_TRACE ("\n")
2094   if (sec_dat.chain)
2095     free (sec_dat.chain);
2096   *dat = old_dat; // unrestrict
2097   return error;
2098 }
2099 
2100 /* r21 Security Section, if saved with password
2101  */
2102 static int
read_2007_section_security(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)2103 read_2007_section_security (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
2104                            r2007_section *restrict sections_map,
2105                            r2007_page *restrict pages_map)
2106 {
2107   Bit_Chain old_dat, sec_dat = { 0 };
2108   int error;
2109   Bit_Chain *str_dat;
2110   Dwg_Security *_obj = &dwg->security;
2111   Dwg_Object *obj = NULL;
2112   BITCODE_RL rcount1 = 0, rcount2 = 0;
2113 
2114   // compressed, page size: 0x7400
2115   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
2116                              SECTION_SECURITY);
2117   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
2118     {
2119       LOG_INFO ("%s section not found\n", "Security");
2120       if (sec_dat.chain)
2121         free (sec_dat.chain);
2122       return 0;
2123     }
2124 
2125   LOG_TRACE ("Security (%lu)\n-------------------\n", sec_dat.size)
2126   old_dat = *dat;
2127   str_dat = dat = &sec_dat; // restrict in size
2128   bit_chain_set_version (&old_dat, dat);
2129 
2130   // clang-format off
2131   #include "security.spec"
2132   // clang-format on
2133 
2134   LOG_TRACE ("\n")
2135   if (sec_dat.chain)
2136     free (sec_dat.chain);
2137   *dat = old_dat; // unrestrict
2138   return error;
2139 }
2140 
2141 #if 0
2142 /* Signature Section, not written nor documented by Teigha
2143  */
2144 static int
2145 read_2007_section_signature (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
2146                            r2007_section *restrict sections_map,
2147                            r2007_page *restrict pages_map)
2148 {
2149   Bit_Chain old_dat, sec_dat = { 0 };
2150   int error;
2151   Bit_Chain *str_dat;
2152   struct Dwg_Signature *_obj = &dwg->signature;
2153   Dwg_Object *obj = NULL;
2154   BITCODE_RL rcount1 = 0, rcount2 = 0;
2155 
2156   // compressed, page size: 0x7400
2157   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
2158                              SECTION_SIGNATURE);
2159   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
2160     {
2161       LOG_INFO ("%s section not found\n", "Signature");
2162       if (sec_dat.chain)
2163         free (sec_dat.chain);
2164       return 0;
2165     }
2166 
2167   LOG_TRACE ("Signature (%lu)\n-------------------\n", sec_dat.size)
2168   old_dat = *dat;
2169   str_dat = dat = &sec_dat; // restrict in size
2170   bit_chain_set_version (&old_dat, dat);
2171 
2172   // clang-format off
2173   #include "signature.spec"
2174   // clang-format on
2175 
2176   LOG_TRACE ("\n")
2177   if (sec_dat.chain)
2178     free (sec_dat.chain);
2179   *dat = old_dat; // unrestrict
2180   return error;
2181 }
2182 #endif
2183 
2184 static int
acds_private(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)2185 acds_private (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2186 {
2187   Bit_Chain *str_dat = dat;
2188   Dwg_AcDs *_obj = &dwg->acds;
2189   Dwg_Object *obj = NULL;
2190   int error = 0;
2191   BITCODE_BL rcount1 = 0, rcount2 = 0;
2192   BITCODE_BL rcount3 = 0, rcount4, vcount;
2193 
2194   // clang-format off
2195   #include "acds.spec"
2196   // clang-format on
2197 
2198   return error;
2199 }
2200 
2201 /* r2013+ datastorage Section, if saved with binary ACIS SAB data
2202  */
2203 static int
read_2007_section_acds(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)2204 read_2007_section_acds (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
2205                         r2007_section *restrict sections_map,
2206                         r2007_page *restrict pages_map)
2207 {
2208   Bit_Chain old_dat, sec_dat = { 0 };
2209   int error;
2210   Bit_Chain *str_dat;
2211   const char *secname = "AcDsPrototype_1b";
2212   Dwg_AcDs *_obj = &dwg->acds;
2213   Dwg_Object *obj = NULL;
2214   BITCODE_RL rcount1 = 0, rcount2 = 0;
2215 
2216   // compressed, pagesize 0x7400, type 13
2217   error = read_data_section (&sec_dat, dat, sections_map, pages_map, SECTION_ACDS);
2218   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
2219     {
2220       LOG_INFO ("%s section not found\n", secname);
2221       if (sec_dat.chain)
2222         free (sec_dat.chain);
2223       return 0;
2224     }
2225 
2226   LOG_TRACE ("AcDs datastorage (%lu)\n-------------------\n", sec_dat.size)
2227   old_dat = *dat;
2228   str_dat = dat = &sec_dat; // restrict in size
2229   bit_chain_set_version (&old_dat, dat);
2230 
2231   error |= acds_private (dat, dwg);
2232   error &= ~DWG_ERR_SECTIONNOTFOUND;
2233 
2234   LOG_TRACE ("\n")
2235   if (sec_dat.chain)
2236     free (sec_dat.chain);
2237   *dat = old_dat; // unrestrict
2238   return error;
2239 }
2240 
2241 static int
read_2007_section_preview(Bit_Chain * restrict dat,Dwg_Data * restrict dwg,r2007_section * restrict sections_map,r2007_page * restrict pages_map)2242 read_2007_section_preview (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
2243                            r2007_section *restrict sections_map,
2244                            r2007_page *restrict pages_map)
2245 {
2246   static Bit_Chain sec_dat = { 0 };
2247   int error;
2248   BITCODE_RL size;
2249   unsigned char *sentinel;
2250 
2251   error = read_data_section (&sec_dat, dat, sections_map, pages_map,
2252                              SECTION_PREVIEW);
2253   if (error >= DWG_ERR_CRITICAL || !sec_dat.chain)
2254     {
2255       LOG_ERROR ("Failed to read uncompressed %s section", "Preview");
2256       if (sec_dat.chain)
2257         free (sec_dat.chain);
2258       return error;
2259     }
2260 
2261   if (dwg->header.thumbnail_address != (BITCODE_RL)dat->byte)
2262     LOG_WARN ("thumbnail_address mismatch: " FORMAT_RL " != %lu",
2263               dwg->header.thumbnail_address, dat->byte);
2264   LOG_TRACE ("\nPreview (%lu)\n-------------------\n", sec_dat.size)
2265   if (!sec_dat.chain || sec_dat.size < 32)
2266     {
2267       LOG_WARN ("Empty thumbnail");
2268       if (sec_dat.chain)
2269         free (sec_dat.chain);
2270       return error;
2271     }
2272 
2273   sentinel = dwg_sentinel (DWG_SENTINEL_THUMBNAIL_BEGIN);
2274   if (memcmp (sentinel, sec_dat.chain, 16))
2275     {
2276       LOG_WARN ("thumbnail sentinel mismatch");
2277       return error |= DWG_ERR_WRONGCRC;
2278     }
2279 
2280   assert (sec_dat.size >= 32);
2281   assert (sec_dat.chain);
2282   dwg->thumbnail.size = sec_dat.size - 32; // 2x sentinel
2283   dwg->thumbnail.chain = sec_dat.chain;
2284   dwg->thumbnail.byte = 16; // sentinel
2285 
2286   dwg_bmp (dwg, &size);
2287   if (abs ((int)((long)size - (long)dwg->thumbnail.size))
2288       > 200) // various headers
2289     LOG_WARN ("thumbnail.size mismatch: %lu != " FORMAT_RL,
2290               dwg->thumbnail.size, size);
2291 
2292   dat->byte += dwg->thumbnail.size;
2293 
2294   return error;
2295 }
2296 
2297 /* exported */
2298 void
read_r2007_init(Dwg_Data * restrict dwg)2299 read_r2007_init (Dwg_Data *restrict dwg)
2300 {
2301   if (dwg->opts)
2302     loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
2303 }
2304 
2305 int
read_r2007_meta_data(Bit_Chain * dat,Bit_Chain * hdl_dat,Dwg_Data * restrict dwg)2306 read_r2007_meta_data (Bit_Chain *dat, Bit_Chain *hdl_dat,
2307                       Dwg_Data *restrict dwg)
2308 {
2309   r2007_file_header file_header;
2310   r2007_page *restrict pages_map = NULL, *restrict page;
2311   r2007_section *restrict sections_map = NULL;
2312   int error;
2313 #ifdef USE_TRACING
2314   char *probe;
2315 #endif
2316 
2317   read_r2007_init (dwg);
2318 #ifdef USE_TRACING
2319   probe = getenv ("LIBREDWG_TRACE");
2320   if (probe)
2321     loglevel = atoi (probe);
2322 #endif
2323   // @ 0x62
2324   error = read_file_header (dat, &file_header);
2325   if (error >= DWG_ERR_VALUEOUTOFBOUNDS)
2326     return error;
2327 
2328   // Pages Map
2329   dat->byte += 0x28; // overread check data
2330   dat->byte += file_header.pages_map_offset;
2331   if ((unsigned long)file_header.pages_map_size_comp
2332       > dat->size - dat->byte)
2333     {
2334       LOG_ERROR ("%s Invalid pages_map_size_comp %lu > %lu bytes left",
2335                  __FUNCTION__,
2336                  (unsigned long)file_header.pages_map_size_comp,
2337                  dat->size - dat->byte)
2338       error |= DWG_ERR_VALUEOUTOFBOUNDS;
2339       goto error;
2340     }
2341   pages_map = read_pages_map (dat, file_header.pages_map_size_comp,
2342                               file_header.pages_map_size_uncomp,
2343                               file_header.pages_map_correction);
2344   if (!pages_map)
2345     return DWG_ERR_PAGENOTFOUND; // Error already logged
2346 
2347   // Sections Map
2348   page = get_page (pages_map, file_header.sections_map_id);
2349   if (!page)
2350     {
2351       LOG_ERROR ("Failed to find sections page map %d",
2352                  (int)file_header.sections_map_id);
2353       error |= DWG_ERR_SECTIONNOTFOUND;
2354       goto error;
2355     }
2356   dat->byte = page->offset;
2357   if ((unsigned long)file_header.sections_map_size_comp
2358       > dat->size - dat->byte)
2359     {
2360       LOG_ERROR ("%s Invalid comp_data_size %lu > %lu bytes left",
2361                  __FUNCTION__,
2362                  (unsigned long)file_header.sections_map_size_comp,
2363                  dat->size - dat->byte)
2364       error |= DWG_ERR_VALUEOUTOFBOUNDS;
2365       goto error;
2366     }
2367   sections_map = read_sections_map (dat, file_header.sections_map_size_comp,
2368                                     file_header.sections_map_size_uncomp,
2369                                     file_header.sections_map_correction);
2370   if (!sections_map)
2371     goto error;
2372 
2373   error = read_2007_section_header (dat, hdl_dat, dwg, sections_map,
2374                                     pages_map);
2375   if (dwg->header.summaryinfo_address)
2376     error |= read_2007_section_summary (dat, dwg, sections_map, pages_map);
2377   error |= read_2007_section_classes (dat, dwg, sections_map, pages_map);
2378   error |= read_2007_section_handles (dat, hdl_dat, dwg, sections_map,
2379                                       pages_map);
2380   error |= read_2007_section_auxheader (dat, dwg, sections_map, pages_map);
2381   if (dwg->header.thumbnail_address)
2382     error |= read_2007_section_preview (dat, dwg, sections_map, pages_map);
2383   error |= read_2007_section_appinfo (dat, dwg, sections_map, pages_map);
2384   error |= read_2007_section_appinfohistory (dat, dwg, sections_map, pages_map);
2385   error |= read_2007_section_filedeplist (dat, dwg, sections_map, pages_map);
2386   error |= read_2007_section_security (dat, dwg, sections_map, pages_map);
2387   error |= read_2007_section_revhistory (dat, dwg, sections_map, pages_map);
2388   error |= read_2007_section_objfreespace (dat, dwg, sections_map, pages_map);
2389   error |= read_2007_section_template (dat, dwg, sections_map, pages_map);
2390   if (dwg->header.vbaproj_address)
2391     error |= read_2007_section_vbaproject (dat, dwg, sections_map, pages_map);
2392   //error |= read_2007_section_signature (dat, dwg, sections_map, pages_map);
2393   error |= read_2007_section_acds (dat, dwg, sections_map, pages_map);
2394   // read_2007_blocks (dat, hdl_dat, dwg, sections_map, pages_map);
2395 
2396 error:
2397   pages_destroy (pages_map);
2398   if (sections_map)
2399     sections_destroy (sections_map);
2400 
2401   return error;
2402 }
2403