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:
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
add_existing_group_input_fn(params, interface_socket);
|
||||
},
|
||||
weight});
|
||||
weight--;
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 : "";
|
||||
|
||||
Reference in New Issue
Block a user