Skip to content

Ignore/skip invalid objects #889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ project(libredwg C)
# Supported options -DLIBREDWG_LIBONLY=On
# -DLIBREDWG_DISABLE_WRITE=On
# -DLIBREDWG_DISABLE_JSON=On
# -DLIBREDWG_DISABLE_DXF=On
# -DLIBREDWG_DISABLE_IGNORE_INVALID_DXF=On
# -DENABLE_MIMALLOC=On
# -DENABLE_LTO=Off
# -DDXF_PRECISION=6
Expand Down Expand Up @@ -35,6 +37,8 @@ option(ENABLE_LTO "IPO/LTO Link Time Optimizations (default ON)" ON)
# FIXME enable
# option(LIBREDWG_DISABLE_BINDINGS "no libredwg perl and python bindings" ON)
option(LIBREDWG_DISABLE_JSON "no libredwg json support" OFF)
option(LIBREDWG_DISABLE_DXF "no libredwg dxf support" OFF)
option(LIBREDWG_DISABLE_IGNORE_INVALID_DXF "stop when invalid DXF object/entity encountered (don't skip)" OFF)
# Rather disable installing a crippled shared lib.
# Only use these for static in-tree libs.
if (LIBREDWG_DISABLE_JSON)
Expand Down
1 change: 1 addition & 0 deletions include/dwg.h
Original file line number Diff line number Diff line change
Expand Up @@ -8978,6 +8978,7 @@ typedef struct _dwg_object
size_t hdlpos; /* relative offset, in bits */
BITCODE_B was_bitsize_set; /* internally for encode only */
BITCODE_B has_strings; /*!< r2007+ */
BITCODE_B invalid; /*!< if object could not be completely processed */
BITCODE_RL stringstream_size; /*!< r2007+ in bits, unused */
BITCODE_UMC handlestream_size; /*!< r2010+ in bits */
size_t common_size; /* relative offset from type ... end common_entity_data */
Expand Down
3 changes: 2 additions & 1 deletion src/bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ typedef struct _bit_chain
Dwg_Version_Type from_version;
FILE *fh;
BITCODE_RS codepage;
unsigned int dxf_line_number;
} Bit_Chain;

#define EMPTY_CHAIN(size) \
{ \
NULL, size, 0UL, 0, 0, R_INVALID, R_INVALID, NULL, 0 \
NULL, size, 0UL, 0, 0, R_INVALID, R_INVALID, NULL, 0, -1 \
}

// only if from r2007+ DWG, not JSON, DXF, add API
Expand Down
3 changes: 3 additions & 0 deletions src/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
/* Define to disable DXF, JSON and other in/out modules. */
#undef DISABLE_DXF

/* Define to stop on invalid DXF, instead of skipping invalid objects/entities. */
#undef DISABLE_IGNORE_INVALID_DXF

/* Define to disable JSON and GeoJSON in/out modules. */
#undef DISABLE_JSON

Expand Down
45 changes: 32 additions & 13 deletions src/encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1174,6 +1174,7 @@ typedef struct
BITCODE_RLL handle;
size_t address;
BITCODE_BL index;
BITCODE_B invalid;
} Object_Map;

/*--------------------------------------------------------------------------------
Expand Down Expand Up @@ -2525,14 +2526,14 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
for (i = 0; i < dwg->num_objects; i++)
{
Dwg_Object *obj = &dwg->object[i];
if (obj->fixedtype == DWG_TYPE_UNKNOWN_OBJ
if (!obj->invalid && (obj->fixedtype == DWG_TYPE_UNKNOWN_OBJ
|| obj->fixedtype == DWG_TYPE_UNKNOWN_ENT
// WIPEOUT causes hang, TABLEGEOMETRY crash, MATERIAL causes ODA errors
#ifndef DEBUG_CLASSES
|| (dwg->opts & DWG_OPTS_IN
&& (obj->fixedtype == DWG_TYPE_WIPEOUT
|| obj->fixedtype == DWG_TYPE_TABLEGEOMETRY
|| obj->fixedtype == DWG_TYPE_MATERIAL))
|| obj->fixedtype == DWG_TYPE_MATERIAL)))
#endif
)
{
Expand Down Expand Up @@ -2561,6 +2562,8 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
for (i = 0; i < dwg->num_objects; i++)
{
Dwg_Object *obj = &dwg->object[i];
if (obj->invalid)
continue;
if (obj->fixedtype == DWG_TYPE_UNKNOWN_OBJ
|| obj->fixedtype == DWG_TYPE_UNKNOWN_ENT
#ifndef DEBUG_CLASSES
Expand Down Expand Up @@ -2596,6 +2599,8 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
for (i = 0; i < dwg->num_objects; i++)
{
Dwg_Object *obj = &dwg->object[i];
if (obj->invalid)
continue;
if (obj->fixedtype == DWG_TYPE_MLEADERSTYLE)
downconvert_MLEADERSTYLE (obj);
else if (obj->fixedtype == DWG_TYPE_DIMSTYLE)
Expand Down Expand Up @@ -3350,21 +3355,31 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
{
LOG_HANDLE ("\nSorting objects...\n");
for (i = 0; i < dwg->num_objects; i++)
fprintf (OUTPUT, "Object(%3i): " FORMAT_RLLx " / idx: %u\n", i,
dwg->object[i].handle.value, dwg->object[i].index);
if (!dwg->object[i].invalid)
fprintf (OUTPUT, "Object(%3i): " FORMAT_RLLx " / idx: %u\n", i,
dwg->object[i].handle.value, dwg->object[i].index);
}
// init unsorted
for (i = 0; i < dwg->num_objects; i++)
{
Dwg_Object *obj = &dwg->object[i];
if (obj->invalid)
{
omap[i].invalid = 1;
LOG_TRACE ("Skip invalid object %s " FORMAT_BL "\n",
obj->name ? obj->name : "", i)
continue;
}
if (obj->type == DWG_TYPE_UNUSED)
{
omap[i].invalid = 1;
LOG_TRACE ("Skip unused object %s " FORMAT_BL " " FORMAT_RLLx "\n",
obj->name ? obj->name : "", i, obj->handle.value)
continue;
}
if (obj->type == DWG_TYPE_FREED)
{
omap[i].invalid = 1;
LOG_TRACE ("Skip freed object %s " FORMAT_BL " " FORMAT_RLLx "\n",
obj->name ? obj->name : "", i, obj->handle.value)
continue;
Expand All @@ -3389,8 +3404,9 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
{
LOG_HANDLE ("\nSorted handles:\n");
for (i = 0; i < dwg->num_objects; i++)
fprintf (OUTPUT, "Handle(%3i): " FORMAT_RLLx " / idx: " FORMAT_BL "\n",
i, omap[i].handle, omap[i].index);
if (!omap[i].invalid)
fprintf (OUTPUT, "Handle(%3i): " FORMAT_RLLx " / idx: " FORMAT_BL "\n",
i, omap[i].handle, omap[i].index);
}

UNTIL (R_2000)
Expand All @@ -3406,7 +3422,7 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
BITCODE_UMC hdloff = omap[i].handle - (i ? omap[i - 1].handle : 0);
BITCODE_MC off = (dat->byte - (i ? omap[i - 1].address : 0)) & INT32_MAX;
size_t end_address;
if (!index && !omap[i].handle)
if (omap[i].invalid || (!index && !omap[i].handle))
continue; // skipped objects
LOG_TRACE ("\n> Next object: " FORMAT_BL " Handleoff: " FORMAT_UMC
" [UMC] Offset: " FORMAT_MC " [MC] @%" PRIuSIZE "\n"
Expand Down Expand Up @@ -3463,9 +3479,10 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
{
LOG_HANDLE ("\nSorted objects:\n");
for (i = 0; i < dwg->num_objects; i++)
LOG_HANDLE ("Object(%d): " FORMAT_RLLx " / Address: %" PRIuSIZE
" / Idx: " FORMAT_BL "\n",
i, omap[i].handle, omap[i].address, omap[i].index);
if (!omap[i].invalid)
LOG_HANDLE ("Object(%d): " FORMAT_RLLx " / Address: %" PRIuSIZE
" / Idx: " FORMAT_BL "\n",
i, omap[i].handle, omap[i].address, omap[i].index);
}
bit_write_CRC (dat, pvzadr, 0xC0C1);

Expand Down Expand Up @@ -3498,7 +3515,7 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
BITCODE_MC offset;

index = omap[i].index;
if (!index && !omap[i].handle)
if (omap[i].invalid || (!index && !omap[i].handle))
continue; // skipped objects
handleoff = omap[i].handle - last_handle;
bit_write_UMC (dat, handleoff);
Expand Down Expand Up @@ -3654,7 +3671,7 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
{ \
unsigned char chain[8]; \
Bit_Chain hdat \
= { chain, 8L, 0L, 0, 0, R_INVALID, R_INVALID, NULL, 30 }; \
= { chain, 8L, 0L, 0, 0, R_INVALID, R_INVALID, NULL, 30, -1 }; \
bit_H_to_dat (&hdat, &dwg->header_vars.NAM->handleref); \
_obj->handles[i].name = #NAM; \
for (int k = 0; k < MIN ((int)_obj->handles[i].num_hdl, 8); k++) \
Expand Down Expand Up @@ -4238,7 +4255,7 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
Dwg_R2004_Header *_obj = &dwg->r2004_header;
Bit_Chain file_dat = {
NULL, sizeof (Dwg_R2004_Header), 0UL, 0, 0, R_INVALID, R_INVALID, NULL,
30
30, -1
};
Bit_Chain *orig_dat = dat;
/* "AcFssFcAJMB" encrypted: 6840F8F7922AB5EF18DD0BF1 */
Expand Down Expand Up @@ -4672,6 +4689,8 @@ encode_preR13_entities (EntitySectionIndexR11 section, Bit_Chain *restrict dat,
{
Dwg_Object *obj = &dwg->object[index];
size_t size_pos = 0UL;
if (obj->invalid)
continue;
// skip table objects or uninitialized entities
if (obj->supertype != DWG_SUPERTYPE_ENTITY || !obj->tio.entity)
{
Expand Down
33 changes: 28 additions & 5 deletions src/in_dxf.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,28 @@ static array_hdls *obj_hdls = NULL;
pair = dxf_read_pair (dat); \
EXPECT_T_DXF (#field, dxf); \
}
#ifndef DISABLE_IGNORE_INVALID_DXF
# define HANDLE_INVALID(kind) \
LOG_WARN ("DXF line %d: Failed to process %s in %s - SKIPPING", \
dat->dxf_line_number, dxfname, #kind); \
free (dxfname); \
obj->invalid = 1; \
for (;;) { \
pair = dxf_read_pair (dat); \
DXF_CHECK_EOF; \
if (pair == NULL || pair->code == 0) { \
break; \
} \
dxf_free_pair(pair); \
}
#else
# define HANDLE_INVALID(kind) \
LOG_WARN ("DXF line %d: Failed to process %s in %s", \
dat->dxf_line_number, dxfname, #kind); \
free (dxfname); \
obj->invalid = 1; \
return DWG_ERR_INVALIDDWG;
#endif

static void *
xcalloc (size_t n, size_t s)
Expand Down Expand Up @@ -586,7 +608,9 @@ dxf_read_pair (Bit_Chain *dat)
return NULL;
}
if (is_binary)
LOG_HANDLE ("%4zx: ", dat->byte);
LOG_HANDLE ("%4zx: ", dat->byte)
else
dat->dxf_line_number += 2;
pair->code = (short)dxf_read_rs (dat);
if (dat->size - dat->byte < 4) // at least EOF\n
goto err;
Expand Down Expand Up @@ -12326,10 +12350,9 @@ dxf_entities_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
if (!pair)
{
Dwg_Object *obj = &dwg->object[idx];
free (dxfname);
if (idx != dwg->num_objects)
obj->dxfname = NULL;
return DWG_ERR_INVALIDDWG;
HANDLE_INVALID(entities)
}
if (pair->code == 0 && pair->value.s)
{
Expand Down Expand Up @@ -12398,10 +12421,9 @@ dxf_objects_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
if (!pair)
{
Dwg_Object *obj = &dwg->object[idx];
free (dxfname);
if (idx != dwg->num_objects)
obj->dxfname = NULL;
return DWG_ERR_INVALIDDWG;
HANDLE_INVALID(objects)
}
}
else
Expand Down Expand Up @@ -12772,6 +12794,7 @@ dwg_read_dxf (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
int error = 0;

loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
dat->dxf_line_number = -1;
if (!dat->chain && dat->fh)
{
error = dat_read_stream (dat, dat->fh);
Expand Down
14 changes: 8 additions & 6 deletions src/out_dxf.c
Original file line number Diff line number Diff line change
Expand Up @@ -3637,7 +3637,8 @@ dxf_entities_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
while (obj)
{
int i = obj->index;
error |= dwg_dxf_object (dat, obj, &i);
if (!obj->invalid)
error |= dwg_dxf_object (dat, obj, &i);
obj = get_next_owned_block_entity (ms, obj); // until last_entity
}
// Then all pspace entities. just filter out other BLOCKS entities
Expand All @@ -3647,7 +3648,8 @@ dxf_entities_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
while (obj)
{
int i = obj->index;
error |= dwg_dxf_object (dat, obj, &i);
if (!obj->invalid)
error |= dwg_dxf_object (dat, obj, &i);
obj = get_next_owned_block_entity (ps, obj);
}
}
Expand All @@ -3661,7 +3663,7 @@ dxf_entities_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
{
int i = obj->index;
Dwg_Object_Ref *owner = obj->tio.entity->ownerhandle;
if (!owner || (owner->obj == ms || owner->obj == ps))
if (!obj->invalid && (!owner || (owner->obj == ms || owner->obj == ps)))
error |= dwg_dxf_object (dat, obj, &i);
obj = dwg_next_entity (obj);
}
Expand All @@ -3674,7 +3676,7 @@ dxf_entities_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
&& obj->type != DWG_TYPE_ENDBLK)
{
Dwg_Object_Ref *owner = obj->tio.entity->ownerhandle;
if (!owner || (owner->obj == ms || owner->obj == ps))
if (!obj->invalid && (!owner || (owner->obj == ms || owner->obj == ps)))
error |= dwg_dxf_object (dat, obj, &i);
}
}
Expand Down Expand Up @@ -3709,12 +3711,12 @@ dxf_objects_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
// The NOD (Named Object Dict) must be always the very first OBJECT,
// not just DICTIONARY.
nod = dwg_get_first_object (dwg, DWG_TYPE_DICTIONARY);
if (nod)
if (nod && !nod->invalid)
error |= dwg_dxf_object (dat, nod, &i);
for (i = 0; (BITCODE_BL)i < dwg->num_objects; i++)
{
const Dwg_Object *restrict obj = &dwg->object[i];
if (obj == nod)
if (obj == nod || obj->invalid)
continue;
if (obj->supertype == DWG_SUPERTYPE_OBJECT
&& obj->type != DWG_TYPE_BLOCK_HEADER && !dwg_obj_is_control (obj))
Expand Down
10 changes: 6 additions & 4 deletions src/out_dxfb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2404,7 +2404,8 @@ dxfb_entities_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
while (obj)
{
int i = obj->index;
error |= dwg_dxfb_object (dat, obj, &i);
if (!obj->invalid)
error |= dwg_dxfb_object (dat, obj, &i);
obj = get_next_owned_block_entity (ms, obj); // until last_entity
}
// Then all pspace entities. just filter out other BLOCKS entities
Expand All @@ -2414,7 +2415,8 @@ dxfb_entities_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
while (obj)
{
int i = obj->index;
error |= dwg_dxfb_object (dat, obj, &i);
if (!obj->invalid)
error |= dwg_dxfb_object (dat, obj, &i);
obj = get_next_owned_block_entity (ps, obj);
}
}
Expand All @@ -2433,12 +2435,12 @@ dxfb_objects_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
// The NOD (Named Object Dict) must be always the very first OBJECT,
// not just DICTIONARY.
nod = dwg_get_first_object (dwg, DWG_TYPE_DICTIONARY);
if (nod)
if (nod && !nod->invalid)
error |= dwg_dxfb_object (dat, nod, &i);
for (i = 0; (BITCODE_BL)i < dwg->num_objects; i++)
{
const Dwg_Object *restrict obj = &dwg->object[i];
if (obj == nod)
if (obj == nod || obj->invalid)
continue;
if (obj->supertype == DWG_SUPERTYPE_OBJECT
&& obj->type != DWG_TYPE_BLOCK_HEADER && !dwg_obj_is_control (obj))
Expand Down
2 changes: 2 additions & 0 deletions src/out_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -2285,6 +2285,8 @@ json_objects_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
{
int error;
Dwg_Object *obj = &dwg->object[i];
if (obj->invalid)
continue;
FIRSTPREFIX HASH;
error = dwg_json_object (dat, obj);
ENDHASH
Expand Down