Fix #119554: Remove links to and from unsupported socket types

#114401 added forward compatibility code to remove unsupported socket
types and avoid crashing with unknown default_value data. However, this
did not update link pointers (which haven't been read at that point),
so the tree can end up with dangling pointers.

To fix this, removal of unsupported sockets is moved further back to a
point where links have been read and can be fixed accordingly.

Ported to main from #119630

Pull Request: https://projects.blender.org/blender/blender/pulls/119650
This commit is contained in:
Lukas Tönne
2024-04-06 11:23:53 +02:00
parent 61b28227bb
commit ee1714136e

View File

@@ -975,17 +975,29 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
}
}
static void direct_link_node_socket_list(BlendDataReader *reader, ListBase *socket_list)
static void remove_unsupported_sockets(ListBase *sockets, ListBase *links)
{
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, socket_list) {
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, sockets) {
if (is_node_socket_supported(sock)) {
direct_link_node_socket(reader, sock);
continue;
}
else {
/* Remove unsupported sockets. */
BLI_remlink(socket_list, sock);
MEM_SAFE_FREE(sock);
/* First remove any link pointing to the socket. */
if (links) {
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, links) {
if (link->fromsock == sock || link->tosock == sock) {
BLI_remlink(links, link);
if (link->tosock) {
link->tosock->link = nullptr;
}
MEM_freeN(link);
}
}
}
BLI_remlink(sockets, sock);
MEM_delete(sock->runtime);
MEM_freeN(sock);
}
}
@@ -1157,8 +1169,12 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
BLO_read_data_address(reader, &node->parent);
direct_link_node_socket_list(reader, &node->inputs);
direct_link_node_socket_list(reader, &node->outputs);
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
direct_link_node_socket(reader, sock);
}
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->outputs) {
direct_link_node_socket(reader, sock);
}
/* Socket storage. */
if (node->type == CMP_NODE_OUTPUT_FILE) {
@@ -1173,8 +1189,12 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
/* Read legacy interface socket lists for versioning. */
BLO_read_list(reader, &ntree->inputs_legacy);
BLO_read_list(reader, &ntree->outputs_legacy);
direct_link_node_socket_list(reader, &ntree->inputs_legacy);
direct_link_node_socket_list(reader, &ntree->outputs_legacy);
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->inputs_legacy) {
direct_link_node_socket(reader, sock);
}
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->outputs_legacy) {
direct_link_node_socket(reader, sock);
}
ntree->tree_interface.read_data(reader);
@@ -1185,6 +1205,13 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
BLO_read_data_address(reader, &link->tosock);
}
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
remove_unsupported_sockets(&node->inputs, &ntree->links);
remove_unsupported_sockets(&node->outputs, &ntree->links);
}
remove_unsupported_sockets(&ntree->inputs_legacy, nullptr);
remove_unsupported_sockets(&ntree->outputs_legacy, nullptr);
BLO_read_data_address(reader, &ntree->geometry_node_asset_traits);
BLO_read_data_address(reader, &ntree->nested_node_refs);