diff options
author | Chris Blackbourn <chrisbblend@gmail.com> | 2022-07-21 06:15:38 +0300 |
---|---|---|
committer | Chris Blackbourn <chrisbblend@gmail.com> | 2022-07-21 06:24:38 +0300 |
commit | c171e8b95c0035eb92d2dcec6e9d82e094954d84 (patch) | |
tree | 02315a8643fe422550e02e29d38912b80b029684 /source/blender/blenkernel/intern/customdata.cc | |
parent | 46a2592eef90782bea6124767c072f275330bd00 (diff) |
Fix T90620: Ignore missing UV data caused by corrupt .blend file
Add crash protection and partial recovery for corrupt .blend files,
particularly for missing UV data.
Differential Revision: https://developer.blender.org/D15489
Diffstat (limited to 'source/blender/blenkernel/intern/customdata.cc')
-rw-r--r-- | source/blender/blenkernel/intern/customdata.cc | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 277218033e9..b990ccbec80 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -4443,9 +4443,48 @@ bool CustomData_verify_versions(CustomData *data, int index) return keeplayer; } +static bool CustomData_layer_ensure_data_exists(CustomDataLayer *layer, size_t count) +{ + BLI_assert(layer); + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); + BLI_assert(typeInfo); + + if (layer->data || count == 0) { + return false; + } + + switch (layer->type) { + /* When more instances of corrupt files are found, add them here. */ + case CD_PROP_BOOL: /* See T84935. */ + case CD_MLOOPUV: /* See T90620. */ + layer->data = MEM_calloc_arrayN(count, typeInfo->size, layerType_getName(layer->type)); + BLI_assert(layer->data); + if (typeInfo->set_default) { + typeInfo->set_default(layer->data, count); + } + return true; + break; + + default: + /* Log an error so we can collect instances of bad files. */ + CLOG_ERROR(&LOG, "CustomDataLayer->data is NULL for type %d.", layer->type); + break; + } + return false; +} + bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, const bool do_fixes) { + BLI_assert(layer); const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); + BLI_assert(typeInfo); + + if (do_fixes) { + CustomData_layer_ensure_data_exists(layer, totitems); + } + + BLI_assert((totitems == 0) || layer->data); + BLI_assert(MEM_allocN_len(layer->data) >= totitems * typeInfo->size); if (typeInfo->validate != nullptr) { return typeInfo->validate(layer->data, totitems, do_fixes); @@ -5206,16 +5245,15 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, int count) if (CustomData_verify_versions(data, i)) { BLO_read_data_address(reader, &layer->data); - if (layer->data == nullptr && count > 0 && layer->type == CD_PROP_BOOL) { - /* Usually this should never happen, except when a custom data layer has not been written - * to a file correctly. */ - CLOG_WARN(&LOG, "Reallocating custom data layer that was not saved correctly."); - const LayerTypeInfo *info = layerType_getInfo(layer->type); - layer->data = MEM_calloc_arrayN((size_t)count, info->size, layerType_getName(layer->type)); - if (info->set_default) { - info->set_default(layer->data, count); - } + if (CustomData_layer_ensure_data_exists(layer, count)) { + /* Under normal operations, this shouldn't happen, but... + * For a CD_PROP_BOOL example, see T84935. + * For a CD_MLOOPUV example, see T90620. */ + CLOG_WARN(&LOG, + "Allocated custom data layer that was not saved correctly for layer->type = %d.", + layer->type); } + if (layer->type == CD_MDISPS) { blend_read_mdisps( reader, count, static_cast<MDisps *>(layer->data), layer->flag & CD_FLAG_EXTERNAL); |