Fix #113860: Nullptr checks for node socket and panel name pointers

In 3.6 the names of node group sockets were using char arrays, but now
use allocated strings. The RNA system assigns nullptr to such strings
when assigning an empty string through python (UI assignment appears to
always generate a valid string). This creates issues with many STL
functions, in particular assigning nullptr to `std::string` will crash.

We have to check for valid pointers before using them in places that
don't handle nullptrs.

Pull Request: https://projects.blender.org/blender/blender/pulls/113924
This commit is contained in:
Lukas Tönne
2023-10-19 11:48:08 +02:00
parent 78b2e9071f
commit dfc3f75e77
8 changed files with 51 additions and 43 deletions

View File

@@ -513,7 +513,7 @@ static void construct_interface_as_legacy_sockets(bNodeTree *ntree)
auto make_legacy_socket = [&](const bNodeTreeInterfaceSocket &socket,
eNodeSocketInOut in_out) -> bNodeSocket * {
bNodeSocket *iosock = make_socket(
ntree, in_out, socket.socket_type, socket.name, socket.identifier);
ntree, in_out, socket.socket_type, socket.name ? socket.name : "", socket.identifier);
if (!iosock) {
return nullptr;
}
@@ -1106,11 +1106,11 @@ void node_update_asset_metadata(bNodeTree &node_tree)
auto outputs = idprop::create_group("outputs");
node_tree.ensure_interface_cache();
for (const bNodeTreeInterfaceSocket *socket : node_tree.interface_inputs()) {
auto property = idprop::create(socket->name, socket->socket_type);
auto property = idprop::create(socket->name ? socket->name : "", socket->socket_type);
IDP_AddToGroup(inputs.get(), property.release());
}
for (const bNodeTreeInterfaceSocket *socket : node_tree.interface_outputs()) {
auto property = idprop::create(socket->name, socket->socket_type);
auto property = idprop::create(socket->name ? socket->name : "", socket->socket_type);
IDP_AddToGroup(outputs.get(), property.release());
}
BKE_asset_metadata_idprop_ensure(asset_data, inputs.release());

View File

@@ -423,10 +423,9 @@ static void item_copy(bNodeTreeInterfaceItem &dst,
bNodeTreeInterfaceSocket &dst_socket = reinterpret_cast<bNodeTreeInterfaceSocket &>(dst);
const bNodeTreeInterfaceSocket &src_socket =
reinterpret_cast<const bNodeTreeInterfaceSocket &>(src);
BLI_assert(src_socket.name != nullptr);
BLI_assert(src_socket.socket_type != nullptr);
dst_socket.name = BLI_strdup(src_socket.name);
dst_socket.name = BLI_strdup_null(src_socket.name);
dst_socket.description = BLI_strdup_null(src_socket.description);
dst_socket.socket_type = BLI_strdup(src_socket.socket_type);
dst_socket.default_attribute_name = BLI_strdup_null(src_socket.default_attribute_name);
@@ -444,9 +443,8 @@ static void item_copy(bNodeTreeInterfaceItem &dst,
bNodeTreeInterfacePanel &dst_panel = reinterpret_cast<bNodeTreeInterfacePanel &>(dst);
const bNodeTreeInterfacePanel &src_panel = reinterpret_cast<const bNodeTreeInterfacePanel &>(
src);
BLI_assert(src_panel.name != nullptr);
dst_panel.name = BLI_strdup(src_panel.name);
dst_panel.name = BLI_strdup_null(src_panel.name);
dst_panel.description = BLI_strdup_null(src_panel.description);
dst_panel.identifier = generate_uid ? generate_uid() : src_panel.identifier;

View File

@@ -891,7 +891,7 @@ static void version_copy_socket(bNodeTreeInterfaceSocket &dst,
char *identifier)
{
/* Node socket copy function based on bNodeTreeInterface::item_copy to avoid using blenkernel. */
dst.name = BLI_strdup(src.name);
dst.name = BLI_strdup_null(src.name);
dst.description = BLI_strdup_null(src.description);
dst.socket_type = BLI_strdup(src.socket_type);
dst.default_attribute_name = BLI_strdup_null(src.default_attribute_name);

View File

@@ -350,7 +350,7 @@ static void add_attribute_search_or_value_buttons(uiLayout *layout,
uiItemL(name_row, "", ICON_NONE);
}
else {
uiItemL(name_row, socket.name, ICON_NONE);
uiItemL(name_row, socket.name ? socket.name : "", ICON_NONE);
}
uiLayout *prop_row = uiLayoutRow(split, true);
@@ -364,7 +364,7 @@ static void add_attribute_search_or_value_buttons(uiLayout *layout,
uiItemR(prop_row, md_ptr, rna_path_attribute_name.c_str(), UI_ITEM_NONE, "", ICON_NONE);
}
else {
const char *name = socket_type == SOCK_BOOLEAN ? socket.name : "";
const char *name = (socket_type == SOCK_BOOLEAN && socket.name) ? socket.name : "";
uiItemR(prop_row, md_ptr, rna_path.c_str(), UI_ITEM_NONE, name, ICON_NONE);
}
@@ -404,29 +404,30 @@ static void draw_property_for_socket(const bNodeTree &node_tree,
/* Use #uiItemPointerR to draw pointer properties because #uiItemR would not have enough
* information about what type of ID to select for editing the values. This is because
* pointer IDProperties contain no information about their type. */
const char *name = socket.name ? socket.name : "";
switch (socket_type) {
case SOCK_OBJECT:
uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "objects", socket.name, ICON_OBJECT_DATA);
uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "objects", name, ICON_OBJECT_DATA);
break;
case SOCK_COLLECTION:
uiItemPointerR(
row, op_ptr, rna_path, bmain_ptr, "collections", socket.name, ICON_OUTLINER_COLLECTION);
row, op_ptr, rna_path, bmain_ptr, "collections", name, ICON_OUTLINER_COLLECTION);
break;
case SOCK_MATERIAL:
uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "materials", socket.name, ICON_MATERIAL);
uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "materials", name, ICON_MATERIAL);
break;
case SOCK_TEXTURE:
uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "textures", socket.name, ICON_TEXTURE);
uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "textures", name, ICON_TEXTURE);
break;
case SOCK_IMAGE:
uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "images", socket.name, ICON_IMAGE);
uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "images", name, ICON_IMAGE);
break;
default:
if (nodes::input_has_attribute_toggle(node_tree, socket_index)) {
add_attribute_search_or_value_buttons(row, op_ptr, socket);
}
else {
uiItemR(row, op_ptr, rna_path, UI_ITEM_NONE, socket.name, ICON_NONE);
uiItemR(row, op_ptr, rna_path, UI_ITEM_NONE, name, ICON_NONE);
}
}
if (!nodes::input_has_attribute_toggle(node_tree, socket_index)) {

View File

@@ -336,12 +336,12 @@ static void gather_socket_link_operations(const bContext &C,
return true;
}
}
search_link_ops.append(
{std::string(IFACE_("Group Input")) + " " + UI_MENU_ARROW_SEP + interface_socket.name,
[interface_socket](nodes::LinkSearchOpParams &params) {
add_existing_group_input_fn(params, interface_socket);
},
weight});
search_link_ops.append({std::string(IFACE_("Group Input")) + " " + UI_MENU_ARROW_SEP +
(interface_socket.name ? interface_socket.name : ""),
[interface_socket](nodes::LinkSearchOpParams &params) {
add_existing_group_input_fn(params, interface_socket);
},
weight});
weight--;
return true;
});

View File

@@ -748,14 +748,17 @@ static void check_property_socket_sync(const Object *ob, ModifierData *md)
geometry_socket_count++;
}
else {
BKE_modifier_set_error(ob, md, "Missing property for input socket \"%s\"", socket->name);
BKE_modifier_set_error(
ob, md, "Missing property for input socket \"%s\"", socket->name ? socket->name : "");
}
continue;
}
if (!nodes::id_property_type_matches_socket(*socket, *property)) {
BKE_modifier_set_error(
ob, md, "Property type does not match input socket \"(%s)\"", socket->name);
BKE_modifier_set_error(ob,
md,
"Property type does not match input socket \"(%s)\"",
socket->name ? socket->name : "");
continue;
}
}
@@ -1494,7 +1497,7 @@ static void add_attribute_search_or_value_buttons(const bContext &C,
uiItemL(name_row, "", ICON_NONE);
}
else {
uiItemL(name_row, socket.name, ICON_NONE);
uiItemL(name_row, socket.name ? socket.name : "", ICON_NONE);
}
uiLayout *prop_row = uiLayoutRow(split, true);
@@ -1508,7 +1511,7 @@ static void add_attribute_search_or_value_buttons(const bContext &C,
uiItemL(layout, "", ICON_BLANK1);
}
else {
const char *name = type == SOCK_BOOLEAN ? socket.name : "";
const char *name = type == (SOCK_BOOLEAN && socket.name) ? socket.name : "";
uiItemR(prop_row, md_ptr, rna_path.c_str(), UI_ITEM_NONE, name, ICON_NONE);
uiItemDecoratorR(layout, md_ptr, rna_path.c_str(), -1);
}
@@ -1561,26 +1564,27 @@ static void draw_property_for_socket(const bContext &C,
* pointer IDProperties contain no information about their type. */
const bNodeSocketType *typeinfo = socket.socket_typeinfo();
const eNodeSocketDatatype type = typeinfo ? eNodeSocketDatatype(typeinfo->type) : SOCK_CUSTOM;
const char *name = socket.name ? socket.name : "";
switch (type) {
case SOCK_OBJECT: {
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "objects", socket.name, ICON_OBJECT_DATA);
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "objects", name, ICON_OBJECT_DATA);
break;
}
case SOCK_COLLECTION: {
uiItemPointerR(
row, md_ptr, rna_path, bmain_ptr, "collections", socket.name, ICON_OUTLINER_COLLECTION);
row, md_ptr, rna_path, bmain_ptr, "collections", name, ICON_OUTLINER_COLLECTION);
break;
}
case SOCK_MATERIAL: {
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "materials", socket.name, ICON_MATERIAL);
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "materials", name, ICON_MATERIAL);
break;
}
case SOCK_TEXTURE: {
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "textures", socket.name, ICON_TEXTURE);
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "textures", name, ICON_TEXTURE);
break;
}
case SOCK_IMAGE: {
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "images", socket.name, ICON_IMAGE);
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "images", name, ICON_IMAGE);
break;
}
default: {
@@ -1588,7 +1592,7 @@ static void draw_property_for_socket(const bContext &C,
add_attribute_search_or_value_buttons(C, row, *nmd, md_ptr, socket);
}
else {
uiItemR(row, md_ptr, rna_path, UI_ITEM_NONE, socket.name, ICON_NONE);
uiItemR(row, md_ptr, rna_path, UI_ITEM_NONE, name, ICON_NONE);
}
}
}
@@ -1612,7 +1616,7 @@ static void draw_property_for_output_socket(const bContext &C,
uiLayout *split = uiLayoutSplit(layout, 0.4f, false);
uiLayout *name_row = uiLayoutRow(split, false);
uiLayoutSetAlignment(name_row, UI_LAYOUT_ALIGN_RIGHT);
uiItemL(name_row, socket.name, ICON_NONE);
uiItemL(name_row, socket.name ? socket.name : "", ICON_NONE);
uiLayout *row = uiLayoutRow(split, true);
add_attribute_search_button(C, row, nmd, md_ptr, rna_path_attribute_name, socket, true);

View File

@@ -2559,14 +2559,16 @@ struct GeometryNodesLazyFunctionBuilder {
for (const bNodeTreeInterfaceSocket *interface_input : btree_.interface_inputs()) {
lf::GraphOutputSocket &lf_socket = lf_graph.add_output(
CPPType::get<bool>(), StringRef("Usage: ") + interface_input->name);
CPPType::get<bool>(),
StringRef("Usage: ") + (interface_input->name ? interface_input->name : ""));
group_input_usage_sockets_.append(&lf_socket);
}
Vector<lf::GraphInputSocket *> lf_output_usages;
for (const bNodeTreeInterfaceSocket *interface_output : btree_.interface_outputs()) {
lf::GraphInputSocket &lf_socket = lf_graph.add_input(
CPPType::get<bool>(), StringRef("Usage: ") + interface_output->name);
CPPType::get<bool>(),
StringRef("Usage: ") + (interface_output->name ? interface_output->name : ""));
group_output_used_sockets_.append(&lf_socket);
lf_output_usages.append(&lf_socket);
}
@@ -3014,8 +3016,9 @@ struct GeometryNodesLazyFunctionBuilder {
const Span<const bNodeTreeInterfaceSocket *> interface_inputs = btree_.interface_inputs();
for (const bNodeTreeInterfaceSocket *interface_input : interface_inputs) {
const bNodeSocketType *typeinfo = interface_input->socket_typeinfo();
lf::GraphInputSocket &lf_socket = lf_graph.add_input(*typeinfo->geometry_nodes_cpp_type,
interface_input->name);
lf::GraphInputSocket &lf_socket = lf_graph.add_input(
*typeinfo->geometry_nodes_cpp_type,
interface_input->name ? interface_input->name : nullptr);
group_input_sockets_.append(&lf_socket);
}
}
@@ -3029,7 +3032,8 @@ struct GeometryNodesLazyFunctionBuilder {
for (const bNodeTreeInterfaceSocket *interface_output : btree_.interface_outputs()) {
const bNodeSocketType *typeinfo = interface_output->socket_typeinfo();
const CPPType &type = *typeinfo->geometry_nodes_cpp_type;
lf::GraphOutputSocket &lf_socket = lf_graph.add_output(type, interface_output->name);
lf::GraphOutputSocket &lf_socket = lf_graph.add_output(
type, interface_output->name ? interface_output->name : "");
lf_socket.set_default_value(type.default_value());
standard_group_output_sockets_.append(&lf_socket);
}
@@ -3196,8 +3200,8 @@ struct GeometryNodesLazyFunctionBuilder {
const bNodeSocket &bsocket = bnode.input_socket(i);
const bNodeSocketType *typeinfo = interface_output.socket_typeinfo();
const CPPType &type = *typeinfo->geometry_nodes_cpp_type;
lf::GraphOutputSocket &lf_socket = graph_params.lf_graph.add_output(type,
interface_output.name);
lf::GraphOutputSocket &lf_socket = graph_params.lf_graph.add_output(
type, interface_output.name ? interface_output.name : "");
lf_graph_outputs.append(&lf_socket);
graph_params.lf_inputs_by_bsocket.add(&bsocket, &lf_socket);
mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
@@ -3851,9 +3855,10 @@ struct GeometryNodesLazyFunctionBuilder {
for (const int i : output_indices.index_range()) {
const int output_index = output_indices[i];
const char *name = btree_.interface_outputs()[output_index]->name;
lf::GraphInputSocket &lf_socket = lf_graph.add_input(
CPPType::get<bke::AnonymousAttributeSet>(),
StringRef("Propagate: ") + btree_.interface_outputs()[output_index]->name);
StringRef("Propagate: ") + (name ? name : ""));
attribute_set_by_geometry_output_.add(output_index, &lf_socket);
}
}

View File

@@ -306,7 +306,7 @@ static SocketDeclarationPtr declaration_for_interface_socket(
dst = std::move(value);
break;
}
dst->name = io_socket.name;
dst->name = io_socket.name ? io_socket.name : "";
dst->identifier = io_socket.identifier;
dst->in_out = in_out;
dst->description = io_socket.description ? io_socket.description : "";