Coverage Report

Created: 2025-10-10 06:21

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