Refactor: Blend file reading asserts for broken pointers #120997
|
@ -5435,7 +5435,7 @@ static void blend_read_paint_mask(BlendDataReader *reader,
|
|||
static void blend_read_layer_data(BlendDataReader *reader, CustomDataLayer &layer, const int count)
|
||||
{
|
||||
const size_t elem_size = CustomData_sizeof(eCustomDataType(layer.type));
|
||||
BLO_read_struct_array(reader, char, elem_size *count, &layer.data);
|
||||
BLO_read_struct_array_allow_broken_pointer(reader, char, elem_size *count, &layer.data);
|
||||
if (CustomData_layer_ensure_data_exists(&layer, count)) {
|
||||
/* Under normal operations, this shouldn't happen, but...
|
||||
* For a CD_PROP_BOOL example, see #84935.
|
||||
|
|
|
@ -337,7 +337,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
BLO_read_struct_array(reader, MEdge, mesh->edges_num, &mesh->medge);
|
||||
BLO_read_struct_array(reader, MFace, mesh->totface_legacy, &mesh->mface);
|
||||
BLO_read_struct_array(reader, MTFace, mesh->totface_legacy, &mesh->mtface);
|
||||
BLO_read_struct_array(reader, MDeformVert, mesh->verts_num, &mesh->dvert);
|
||||
BLO_read_struct_array_allow_broken_pointer(reader, MDeformVert, mesh->verts_num, &mesh->dvert);
|
||||
BLO_read_struct_array(reader, TFace, mesh->totface_legacy, &mesh->tface);
|
||||
BLO_read_struct_array(reader, MCol, mesh->totface_legacy, &mesh->mcol);
|
||||
|
||||
|
|
|
@ -960,7 +960,7 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
|
|||
BLO_read_struct(reader, IDProperty, &sock->prop);
|
||||
IDP_BlendDataRead(reader, &sock->prop);
|
||||
|
||||
BLO_read_struct(reader, bNodeLink, &sock->link);
|
||||
BLO_read_struct_allow_broken_pointer(reader, bNodeLink, &sock->link);
|
||||
sock->typeinfo = nullptr;
|
||||
BLO_read_data_address(reader, &sock->storage);
|
||||
BLO_read_data_address(reader, &sock->default_value);
|
||||
|
@ -1070,7 +1070,7 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
|
|||
* `IDTypeInfo.foreach_cache` callback. */
|
||||
}
|
||||
else {
|
||||
BLO_read_data_address(reader, &node->storage);
|
||||
BLO_read_data_address_allow_broken_pointer(reader, &node->storage);
|
||||
}
|
||||
|
||||
if (node->storage) {
|
||||
|
|
|
@ -728,7 +728,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
}
|
||||
|
||||
/* Only for versioning, vertex group names are now stored on object data. */
|
||||
BLO_read_struct_list(reader, bDeformGroup, &ob->defbase);
|
||||
BLO_read_struct_list_allow_broken_pointer(reader, bDeformGroup, &ob->defbase);
|
||||
BLO_read_struct_list(reader, bFaceMap, &ob->fmaps);
|
||||
|
||||
/* XXX deprecated - old animation system <<< */
|
||||
|
|
|
@ -1356,7 +1356,8 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
else {
|
||||
seqbase_poin = POINTER_OFFSET(ed->seqbasep, -seqbase_offset);
|
||||
|
||||
seqbase_poin = BLO_read_get_new_data_address(reader, seqbase_poin);
|
||||
const bool allow_broken_pointer = true;
|
||||
seqbase_poin = BLO_read_get_new_data_address(reader, seqbase_poin, allow_broken_pointer);
|
||||
|
||||
if (seqbase_poin) {
|
||||
ed->seqbasep = (ListBase *)POINTER_OFFSET(seqbase_poin, seqbase_offset);
|
||||
|
|
|
@ -1136,7 +1136,7 @@ void BKE_screen_area_map_blend_write(BlendWriter *writer, ScrAreaMap *area_map)
|
|||
|
||||
static void direct_link_panel_list(BlendDataReader *reader, ListBase *lb)
|
||||
{
|
||||
BLO_read_struct_list(reader, Panel, lb);
|
||||
BLO_read_struct_list_allow_broken_pointer(reader, Panel, lb);
|
||||
|
||||
LISTBASE_FOREACH (Panel *, panel, lb) {
|
||||
panel->runtime = MEM_new<Panel_Runtime>(__func__);
|
||||
|
@ -1158,9 +1158,10 @@ static void direct_link_region(BlendDataReader *reader, ARegion *region, int spa
|
|||
|
||||
direct_link_panel_list(reader, ®ion->panels);
|
||||
|
||||
BLO_read_struct_list(reader, PanelCategoryStack, ®ion->panels_category_active);
|
||||
BLO_read_struct_list_allow_broken_pointer(
|
||||
reader, PanelCategoryStack, ®ion->panels_category_active);
|
||||
|
||||
BLO_read_struct_list(reader, uiList, ®ion->ui_lists);
|
||||
BLO_read_struct_list_allow_broken_pointer(reader, uiList, ®ion->ui_lists);
|
||||
|
||||
/* The area's search filter is runtime only, so we need to clear the active flag on read. */
|
||||
/* Clear runtime flags (e.g. search filter is runtime only). */
|
||||
|
@ -1173,7 +1174,7 @@ static void direct_link_region(BlendDataReader *reader, ARegion *region, int spa
|
|||
IDP_BlendDataRead(reader, &ui_list->properties);
|
||||
}
|
||||
|
||||
BLO_read_struct_list(reader, uiPreview, ®ion->ui_previews);
|
||||
BLO_read_struct_list_allow_broken_pointer(reader, uiPreview, ®ion->ui_previews);
|
||||
|
||||
if (spacetype == SPACE_EMPTY) {
|
||||
/* unknown space type, don't leak regiondata */
|
||||
|
@ -1250,7 +1251,7 @@ void BKE_screen_view3d_do_versions_250(View3D *v3d, ListBase *regions)
|
|||
|
||||
static void direct_link_area(BlendDataReader *reader, ScrArea *area)
|
||||
{
|
||||
BLO_read_struct_list(reader, SpaceLink, &(area->spacedata));
|
||||
BLO_read_struct_list_allow_broken_pointer(reader, SpaceLink, &(area->spacedata));
|
||||
BLO_read_struct_list(reader, ARegion, &(area->regionbase));
|
||||
|
||||
BLI_listbase_clear(&area->handlers);
|
||||
|
|
|
@ -102,7 +102,7 @@ void BKE_viewer_path_blend_write(BlendWriter *writer, const ViewerPath *viewer_p
|
|||
|
||||
void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer_path)
|
||||
{
|
||||
BLO_read_struct_list(reader, ViewerPathElem, &viewer_path->path);
|
||||
BLO_read_struct_list_allow_broken_pointer(reader, ViewerPathElem, &viewer_path->path);
|
||||
LISTBASE_FOREACH (ViewerPathElem *, elem, &viewer_path->path) {
|
||||
BLO_read_string(reader, &elem->ui_name);
|
||||
switch (ViewerPathElemType(elem->type)) {
|
||||
|
|
|
@ -241,14 +241,20 @@ bool BLO_write_is_undo(BlendWriter *writer);
|
|||
* Avoid using the generic BLO_read_data_address when possible, use typed functions instead.
|
||||
* \{ */
|
||||
|
||||
void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address);
|
||||
void *BLO_read_get_new_data_address(BlendDataReader *reader,
|
||||
const void *old_address,
|
||||
bool allow_broken_pointer = false);
|
||||
void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader,
|
||||
const void *old_address,
|
||||
size_t data_size);
|
||||
void *BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_address);
|
||||
size_t expected_size,
|
||||
bool allow_broken_pointer = false);
|
||||
void *BLO_read_get_new_packed_address(BlendDataReader *reader,
|
||||
const void *old_address,
|
||||
bool allow_broken_pointer = false);
|
||||
void *BLO_read_struct_array_with_size(BlendDataReader *reader,
|
||||
const void *old_address,
|
||||
size_t data_size);
|
||||
size_t expected_size,
|
||||
bool allow_broken_pointer = false);
|
||||
|
||||
#define BLO_read_data_address(reader, ptr_p) \
|
||||
*((void **)ptr_p) = BLO_read_get_new_data_address((reader), *(ptr_p))
|
||||
|
@ -261,15 +267,36 @@ void *BLO_read_struct_array_with_size(BlendDataReader *reader,
|
|||
#define BLO_read_packed_address(reader, ptr_p) \
|
||||
*((void **)ptr_p) = BLO_read_get_new_packed_address((reader), *(ptr_p))
|
||||
|
||||
/* Variations for cases where pointer may exist but is not able
|
||||
* to be resolved. This is generally due to deprecated struct members
|
||||
* that should have been set to null in versioning but were not.
|
||||
*
|
||||
* When using these, the following code must be able to handle the
|
||||
* resulting null pointers.
|
||||
*/
|
||||
#define BLO_read_data_address_allow_broken_pointer(reader, ptr_p) \
|
||||
*((void **)ptr_p) = BLO_read_get_new_data_address((reader), *(ptr_p), true)
|
||||
#define BLO_read_struct_allow_broken_pointer(reader, struct_name, ptr_p) \
|
||||
*((void **)ptr_p) = BLO_read_struct_array_with_size( \
|
||||
reader, *((void **)ptr_p), sizeof(struct_name), true)
|
||||
#define BLO_read_struct_array_allow_broken_pointer(reader, struct_name, array_size, ptr_p) \
|
||||
*((void **)ptr_p) = BLO_read_struct_array_with_size( \
|
||||
reader, *((void **)ptr_p), sizeof(struct_name) * (array_size), true)
|
||||
|
||||
/* Read all elements in list
|
||||
*
|
||||
* Updates all `->prev` and `->next` pointers of the list elements.
|
||||
* Updates the `list->first` and `list->last` pointers.
|
||||
*/
|
||||
void BLO_read_struct_list_with_size(BlendDataReader *reader, size_t elem_size, ListBase *list);
|
||||
void BLO_read_struct_list_with_size(BlendDataReader *reader,
|
||||
size_t elem_size,
|
||||
bool allow_broken_pointer,
|
||||
ListBase *list);
|
||||
|
||||
#define BLO_read_struct_list(reader, struct_name, list) \
|
||||
BLO_read_struct_list_with_size(reader, sizeof(struct_name), list)
|
||||
BLO_read_struct_list_with_size(reader, sizeof(struct_name), false, list)
|
||||
#define BLO_read_struct_list_allow_broken_pointer(reader, struct_name, list) \
|
||||
BLO_read_struct_list_with_size(reader, sizeof(struct_name), true, list)
|
||||
|
||||
/* Update data pointers and correct byte-order if necessary. */
|
||||
|
||||
|
|
|
@ -2117,7 +2117,7 @@ static void direct_link_id_common(
|
|||
|
||||
/* Link direct data of ID properties. */
|
||||
if (id->properties) {
|
||||
BLO_read_struct(reader, IDProperty, &id->properties);
|
||||
BLO_read_struct_allow_broken_pointer(reader, IDProperty, &id->properties);
|
||||
/* this case means the data was written incorrectly, it should not happen */
|
||||
IDP_BlendDataRead(reader, &id->properties);
|
||||
}
|
||||
|
@ -4781,43 +4781,73 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
|
|||
}
|
||||
|
||||
static void *blo_verify_data_address(void *new_address,
|
||||
const void * /*old_address*/,
|
||||
const size_t expected_size)
|
||||
const void *old_address,
|
||||
const size_t expected_size,
|
||||
const bool allow_broken_pointer = false)
|
||||
{
|
||||
if (new_address != nullptr) {
|
||||
if (new_address == nullptr) {
|
||||
if (old_address == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!allow_broken_pointer) {
|
||||
BLI_assert_msg(expected_size == 0, "Corrupt .blend file, expected non-zero data.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Not testing equality, since size might have been aligned up,
|
||||
* or might be passed the size of a base struct with inheritance. */
|
||||
BLI_assert_msg(MEM_allocN_len(new_address) >= expected_size,
|
||||
"Corrupt .blend file, unexpected data size.");
|
||||
BLI_assert_msg(expected_size == 0 || MEM_allocN_len(new_address) >= expected_size,
|
||||
"Corrupt .blend file, unexpected data size");
|
||||
}
|
||||
|
||||
return new_address;
|
||||
}
|
||||
|
||||
void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address)
|
||||
void *BLO_read_get_new_data_address(BlendDataReader *reader,
|
||||
const void *old_address,
|
||||
const bool allow_broken_pointer)
|
||||
{
|
||||
return newdataadr(reader->fd, old_address);
|
||||
void *new_address = newdataadr(reader->fd, old_address);
|
||||
|
||||
if (!allow_broken_pointer) {
|
||||
BLI_assert_msg(old_address == nullptr || new_address != nullptr,
|
||||
"Corrupt .blend file, expected non-zero pointer.");
|
||||
}
|
||||
|
||||
return new_address;
|
||||
}
|
||||
|
||||
void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader,
|
||||
const void *old_address,
|
||||
const size_t expected_size)
|
||||
const size_t expected_size,
|
||||
const bool allow_broken_pointer)
|
||||
{
|
||||
void *new_address = newdataadr_no_us(reader->fd, old_address);
|
||||
return blo_verify_data_address(new_address, old_address, expected_size);
|
||||
return blo_verify_data_address(new_address, old_address, expected_size, allow_broken_pointer);
|
||||
}
|
||||
|
||||
void *BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_address)
|
||||
void *BLO_read_get_new_packed_address(BlendDataReader *reader,
|
||||
const void *old_address,
|
||||
const bool allow_broken_pointer)
|
||||
{
|
||||
return newpackedadr(reader->fd, old_address);
|
||||
void *new_address = newpackedadr(reader->fd, old_address);
|
||||
|
||||
if (!allow_broken_pointer) {
|
||||
BLI_assert_msg(old_address == nullptr || new_address != nullptr,
|
||||
"Corrupt .blend file, expected non-zero pointer.");
|
||||
}
|
||||
|
||||
return new_address;
|
||||
}
|
||||
|
||||
void *BLO_read_struct_array_with_size(BlendDataReader *reader,
|
||||
const void *old_address,
|
||||
const size_t expected_size)
|
||||
const size_t expected_size,
|
||||
const bool allow_broken_pointer)
|
||||
{
|
||||
void *new_address = newdataadr(reader->fd, old_address);
|
||||
return blo_verify_data_address(new_address, old_address, expected_size);
|
||||
return blo_verify_data_address(new_address, old_address, expected_size, allow_broken_pointer);
|
||||
}
|
||||
|
||||
ID *BLO_read_get_new_id_address(BlendLibReader *reader,
|
||||
|
@ -4845,18 +4875,20 @@ bool BLO_read_requires_endian_switch(BlendDataReader *reader)
|
|||
|
||||
void BLO_read_struct_list_with_size(BlendDataReader *reader,
|
||||
const size_t expected_elem_size,
|
||||
const bool allow_broken_pointer,
|
||||
ListBase *list)
|
||||
{
|
||||
if (BLI_listbase_is_empty(list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
list->first = BLO_read_struct_array_with_size(reader, list->first, expected_elem_size);
|
||||
list->first = BLO_read_struct_array_with_size(
|
||||
reader, list->first, expected_elem_size, allow_broken_pointer);
|
||||
Link *ln = static_cast<Link *>(list->first);
|
||||
Link *prev = nullptr;
|
||||
while (ln) {
|
||||
ln->next = static_cast<Link *>(
|
||||
BLO_read_struct_array_with_size(reader, ln->next, expected_elem_size));
|
||||
ln->next = static_cast<Link *>(BLO_read_struct_array_with_size(
|
||||
reader, ln->next, expected_elem_size, allow_broken_pointer));
|
||||
ln->prev = prev;
|
||||
prev = ln;
|
||||
ln = ln->next;
|
||||
|
|
|
@ -312,7 +312,7 @@ static void console_blend_read_data(BlendDataReader *reader, SpaceLink *sl)
|
|||
{
|
||||
SpaceConsole *sconsole = (SpaceConsole *)sl;
|
||||
|
||||
BLO_read_struct_list(reader, ConsoleLine, &sconsole->scrollback);
|
||||
BLO_read_struct_list_allow_broken_pointer(reader, ConsoleLine, &sconsole->scrollback);
|
||||
BLO_read_struct_list(reader, ConsoleLine, &sconsole->history);
|
||||
|
||||
/* Comma expressions, (e.g. expr1, expr2, expr3) evaluate each expression,
|
||||
|
|
|
@ -869,7 +869,8 @@ static void file_space_blend_read_data(BlendDataReader *reader, SpaceLink *sl)
|
|||
sfile->previews_timer = nullptr;
|
||||
sfile->tags = 0;
|
||||
sfile->runtime = nullptr;
|
||||
BLO_read_struct(reader, FileSelectParams, &sfile->params);
|
||||
|
||||
BLO_read_struct_allow_broken_pointer(reader, FileSelectParams, &sfile->params);
|
||||
BLO_read_struct(reader, FileAssetSelectParams, &sfile->asset_params);
|
||||
if (sfile->params) {
|
||||
sfile->params->rename_id = nullptr;
|
||||
|
|
Loading…
Reference in New Issue