Coverage Report

Created: 2026-10-05 07:34

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