BLI: improve UTF-8 safety when copying StringRef to char buffers

Previously, there was a `StringRef.copy` method which would copy the string into
the given buffer. However, it was not defined for the case when the buffer was
too small. It moved the responsibility of making sure the buffer is large enough
to the caller.

Unfortunately, in practice that easily hides bugs in builds without asserts
which don't come up in testing much. Now, the method is replaced with
`StringRef.copy_utf8_truncated` which has much more well defined semantics and
also makes sure that the string remains valid utf-8.

This also renames `unsafe_copy` to `copy_unsafe` to make the naming more similar
to `copy_utf8_truncated`.

Pull Request: https://projects.blender.org/blender/blender/pulls/133677
This commit is contained in:
Jacques Lucke
2025-01-29 12:12:27 +01:00
parent bf2264a3b8
commit e1753900b7
26 changed files with 161 additions and 94 deletions

View File

@@ -162,14 +162,7 @@ void BKE_asset_metadata_catalog_id_set(AssetMetaData *asset_data,
const char *catalog_simple_name)
{
asset_data->catalog_id = catalog_id;
constexpr size_t max_simple_name_length = sizeof(asset_data->catalog_simple_name);
/* The substr() call is necessary to make copy() copy the first N characters (instead of refusing
* to copy and producing an empty string). */
StringRef trimmed_id =
StringRef(catalog_simple_name).trim().substr(0, max_simple_name_length - 1);
trimmed_id.copy(asset_data->catalog_simple_name, max_simple_name_length);
StringRef(catalog_simple_name).trim().copy_utf8_truncated(asset_data->catalog_simple_name);
}
void BKE_asset_metadata_idprop_ensure(AssetMetaData *asset_data, IDProperty *prop)

View File

@@ -22,7 +22,7 @@ std::string frame_to_file_name(const SubFrame &frame)
std::optional<SubFrame> file_name_to_frame(const StringRef file_name)
{
char modified_file_name[FILE_MAX];
file_name.copy(modified_file_name);
file_name.copy_utf8_truncated(modified_file_name);
BLI_string_replace_char(modified_file_name, '_', '.');
try {
const SubFrame frame = std::stof(modified_file_name);

View File

@@ -3165,7 +3165,7 @@ static CustomDataLayer *customData_add_layer__internal(
}
if (!name.is_empty()) {
name.copy(new_layer.name);
name.copy_utf8_truncated(new_layer.name);
CustomData_set_layer_unique_name(data, index);
}
else {
@@ -3790,7 +3790,7 @@ bool CustomData_set_layer_name(CustomData *data,
return false;
}
name.copy(data->layers[layer_index].name);
name.copy_utf8_truncated(data->layers[layer_index].name);
return true;
}
@@ -4570,9 +4570,7 @@ void CustomData_validate_layer_name(const CustomData *data,
BLI_strncpy_utf8(outname, data->layers[index].name, MAX_CUSTOMDATA_LAYER_NAME);
}
else {
char name_c_str[MAX_CUSTOMDATA_LAYER_NAME];
name.copy(name_c_str);
BLI_strncpy_utf8(outname, name_c_str, MAX_CUSTOMDATA_LAYER_NAME);
name.copy_utf8_truncated(outname, MAX_CUSTOMDATA_LAYER_NAME);
}
}

View File

@@ -52,7 +52,7 @@ bDeformGroup *BKE_object_defgroup_new(Object *ob, const StringRef name)
defgroup = MEM_cnew<bDeformGroup>(__func__);
name.copy(defgroup->name);
name.copy_utf8_truncated(defgroup->name);
ListBase *defbase = BKE_object_defgroup_list_mutable(ob);

View File

@@ -1592,7 +1592,7 @@ static void legacy_object_modifier_influence(GreasePencilModifierInfluenceData &
{
influence.flag = 0;
layername.copy(influence.layer_name);
layername.copy_utf8_truncated(influence.layer_name);
if (invert_layer) {
influence.flag |= GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER;
}
@@ -1619,7 +1619,7 @@ static void legacy_object_modifier_influence(GreasePencilModifierInfluenceData &
influence.flag |= GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER;
}
vertex_group_name.copy(influence.vertex_group_name);
vertex_group_name.copy_utf8_truncated(influence.vertex_group_name);
if (invert_vertex_group) {
influence.flag |= GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP;
}

View File

@@ -57,7 +57,7 @@ int ensure_vertex_group(const StringRef name, ListBase &vertex_group_names)
int def_nr = BKE_defgroup_name_index(&vertex_group_names, name);
if (def_nr < 0) {
bDeformGroup *defgroup = MEM_cnew<bDeformGroup>(__func__);
name.copy(defgroup->name);
name.copy_utf8_truncated(defgroup->name);
BLI_addtail(&vertex_group_names, defgroup);
def_nr = BLI_listbase_count(&vertex_group_names) - 1;
BLI_assert(def_nr >= 0);
@@ -81,7 +81,7 @@ void assign_to_vertex_group_from_mask(bke::CurvesGeometry &curves,
/* Lazily add the vertex group if any vertex is selected. */
if (def_nr < 0) {
bDeformGroup *defgroup = MEM_cnew<bDeformGroup>(__func__);
name.copy(defgroup->name);
name.copy_utf8_truncated(defgroup->name);
BLI_addtail(&vertex_group_names, defgroup);
def_nr = BLI_listbase_count(&vertex_group_names) - 1;
BLI_assert(def_nr >= 0);
@@ -114,7 +114,7 @@ void assign_to_vertex_group(Drawing &drawing, const StringRef name, const float
/* Lazily add the vertex group if any vertex is selected. */
if (def_nr < 0) {
bDeformGroup *defgroup = MEM_cnew<bDeformGroup>(__func__);
name.copy(defgroup->name);
name.copy_utf8_truncated(defgroup->name);
BLI_addtail(&vertex_group_names, defgroup);
def_nr = BLI_listbase_count(&vertex_group_names) - 1;

View File

@@ -71,7 +71,7 @@ IDProperty *IDP_NewIDPArray(const blender::StringRef name)
MEM_callocN(sizeof(IDProperty), "IDProperty prop array"));
prop->type = IDP_IDPARRAY;
prop->len = 0;
name.copy(prop->name);
name.copy_utf8_truncated(prop->name);
return prop;
}
@@ -383,7 +383,7 @@ IDProperty *IDP_NewStringMaxSize(const char *st,
}
prop->type = IDP_STRING;
name.copy(prop->name);
name.copy_utf8_truncated(prop->name);
prop->flag = short(flags);
return prop;
@@ -1087,7 +1087,7 @@ IDProperty *IDP_New(const char type,
}
prop->type = type;
name.copy(prop->name);
name.copy_utf8_truncated(prop->name);
prop->flag = short(flags);
return prop;

View File

@@ -486,15 +486,15 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
bNodeSocket *sock = MEM_cnew<bNodeSocket>(__func__);
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
StringRef(stype->idname).copy(sock->idname);
StringRef(stype->idname).copy_utf8_truncated(sock->idname);
sock->in_out = int(in_out);
sock->type = int(SOCK_CUSTOM); /* int type undefined by default */
node_socket_set_typeinfo(ntree, sock, stype);
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
identifier.copy(sock->identifier);
name.copy(sock->name);
identifier.copy_utf8_truncated(sock->identifier);
name.copy_utf8_truncated(sock->name);
sock->storage = nullptr;
sock->flag |= SOCK_COLLAPSED;
@@ -1950,11 +1950,11 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
if (identifier[0] != '\0') {
/* use explicit identifier */
identifier.copy(auto_identifier);
identifier.copy_utf8_truncated(auto_identifier);
}
else {
/* if no explicit identifier is given, assign a unique identifier based on the name */
name.copy(auto_identifier);
name.copy_utf8_truncated(auto_identifier);
}
/* Make the identifier unique. */
BLI_uniquename_cb(
@@ -1967,12 +1967,12 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
STRNCPY(sock->identifier, auto_identifier);
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
name.copy(sock->name);
name.copy_utf8_truncated(sock->name);
sock->storage = nullptr;
sock->flag |= SOCK_COLLAPSED;
sock->type = SOCK_CUSTOM; /* int type undefined by default */
idname.copy(sock->idname);
idname.copy_utf8_truncated(sock->idname);
node_socket_set_typeinfo(ntree, sock, node_socket_type_find(idname));
return sock;
@@ -2132,7 +2132,7 @@ void node_modify_socket_type(bNodeTree *ntree,
}
}
idname.copy(sock->idname);
idname.copy_utf8_truncated(sock->idname);
node_socket_set_typeinfo(ntree, sock, socktype);
}
@@ -2681,7 +2681,7 @@ bNode *node_add_node(const bContext *C, bNodeTree *ntree, const StringRef idname
node_unique_id(ntree, node);
node->ui_order = ntree->all_nodes().size();
idname.copy(node->idname);
idname.copy_utf8_truncated(node->idname);
node_set_typeinfo(C, ntree, node, node_type_find(idname));
BKE_ntree_update_tag_node_new(ntree, node);
@@ -3237,7 +3237,7 @@ static bNodeTree *node_tree_add_tree_do(Main *bmain,
BLI_assert(owner_id == nullptr);
}
idname.copy(ntree->idname);
idname.copy_utf8_truncated(ntree->idname);
ntree_set_typeinfo(ntree, node_tree_type_find(idname));
return ntree;

View File

@@ -161,7 +161,7 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya
{
const int64_t alloc_size = str.size() + 1;
char *buffer = static_cast<char *>(this->allocate(alloc_size, 1));
str.copy(buffer, alloc_size);
str.copy_unsafe(buffer);
return StringRefNull(static_cast<const char *>(buffer));
}

View File

@@ -70,9 +70,20 @@ class StringRefBase {
constexpr IndexRange index_range() const;
void unsafe_copy(char *dst) const;
void copy(char *dst, int64_t dst_size) const;
template<size_t N> void copy(char (&dst)[N]) const;
/**
* Copy the string into a char array. The copied string will be null-terminated. If it does not
* fit, it will be truncated while keeping it valid utf-8 (assuming the #StringRef itself is
* valid utf-8).
*/
void copy_utf8_truncated(char *dst, int64_t dst_size) const;
template<size_t N> void copy_utf8_truncated(char (&dst)[N]) const;
/**
* Copy the string into a buffer. The buffer has to be one byte larger than the size of the
* string, because the copied string will be null-terminated. Only use this when you are
* absolutely sure that the buffer is large enough.
*/
void copy_unsafe(char *dst) const;
constexpr bool startswith(StringRef prefix) const;
constexpr bool endswith(StringRef suffix) const;
@@ -207,12 +218,7 @@ constexpr IndexRange StringRefBase::index_range() const
return IndexRange(size_);
}
/**
* Copy the string into a buffer. The buffer has to be one byte larger than the size of the
* string, because the copied string will be null-terminated. Only use this when you are
* absolutely sure that the buffer is large enough.
*/
inline void StringRefBase::unsafe_copy(char *dst) const
inline void StringRefBase::copy_unsafe(char *dst) const
{
if (size_ > 0) {
memcpy(dst, data_, size_t(size_));
@@ -220,28 +226,9 @@ inline void StringRefBase::unsafe_copy(char *dst) const
dst[size_] = '\0';
}
/**
* Copy the string into a buffer. The copied string will be null-terminated. This invokes
* undefined behavior when dst_size is too small. (Should we define the behavior?)
*/
inline void StringRefBase::copy(char *dst, const int64_t dst_size) const
template<size_t N> inline void StringRefBase::copy_utf8_truncated(char (&dst)[N]) const
{
if (size_ < dst_size) {
this->unsafe_copy(dst);
}
else {
BLI_assert(false);
dst[0] = '\0';
}
}
/**
* Copy the string into a char array. The copied string will be null-terminated. This invokes
* undefined behavior when dst is too small.
*/
template<size_t N> inline void StringRefBase::copy(char (&dst)[N]) const
{
this->copy(dst, N);
this->copy_utf8_truncated(dst, N);
}
/**

View File

@@ -20,6 +20,14 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t
size_t BLI_strncpy_utf8_rlen(char *__restrict dst,
const char *__restrict src,
size_t dst_maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
/**
* A version of #BLI_strncpy_utf8_rlen that doesn't null terminate the string.
* \note Useful for C++ APIs that don't null terminate strings.
*/
size_t BLI_strncpy_utf8_rlen_unterminated(char *__restrict dst,
const char *__restrict src,
size_t dst_maxncpy);
/**
* Find first UTF-8 invalid byte in given \a str, of \a length bytes.
*

View File

@@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_string_ref.hh"
#include "BLI_string_utf8.h"
#include <ostream>
@@ -20,4 +21,23 @@ std::ostream &operator<<(std::ostream &stream, StringRefNull ref)
return stream;
}
void StringRefBase::copy_utf8_truncated(char *dst, const int64_t dst_size) const
{
/* Destination must at least hold the null terminator. */
BLI_assert(dst_size >= 1);
/* The current #StringRef is assumed to contain valid UTF-8. */
BLI_assert(BLI_str_utf8_invalid_byte(data_, size_) == -1);
/* Common case when the string can just be copied over entirely. */
if (size_ < dst_size) {
this->copy_unsafe(dst);
return;
}
const int64_t max_copy_num_without_terminator = std::min(size_, dst_size - 1);
const size_t new_len = BLI_strncpy_utf8_rlen_unterminated(
dst, data_, max_copy_num_without_terminator);
dst[new_len] = '\0';
}
} // namespace blender

View File

@@ -312,15 +312,20 @@ int BLI_str_utf8_invalid_strip(char *str, size_t length)
*
* Compatible with #BLI_strncpy, but ensure no partial UTF8 chars.
*
* \param dst_maxncpy: The maximum number of bytes to copy. This does not include the null
* terminator.
*
* \note currently we don't attempt to deal with invalid utf8 chars.
* See #BLI_str_utf8_invalid_strip for if that is needed.
*
* \note the caller is responsible for null terminating the string.
*/
BLI_INLINE char *str_utf8_copy_max_bytes_impl(char *dst, const char *src, size_t dst_maxncpy)
{
/* Cast to `uint8_t` is a no-op, quiets array subscript of type `char` warning.
* No need to check `src` points to a nil byte as this will return from the switch statement. */
size_t utf8_size;
while ((utf8_size = size_t(utf8_char_compute_skip(*src))) < dst_maxncpy) {
while ((utf8_size = size_t(utf8_char_compute_skip(*src))) <= dst_maxncpy) {
dst_maxncpy -= utf8_size;
/* Prefer more compact block. */
/* NOLINTBEGIN: bugprone-assignment-in-if-condition */
@@ -336,7 +341,6 @@ BLI_INLINE char *str_utf8_copy_max_bytes_impl(char *dst, const char *src, size_t
/* clang-format on */
/* NOLINTEND: bugprone-assignment-in-if-condition */
}
*dst = '\0';
return dst;
}
@@ -345,7 +349,8 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t
BLI_assert(dst_maxncpy != 0);
BLI_string_debug_size(dst, dst_maxncpy);
str_utf8_copy_max_bytes_impl(dst, src, dst_maxncpy);
char *dst_end = str_utf8_copy_max_bytes_impl(dst, src, dst_maxncpy - 1);
*dst_end = '\0';
return dst;
}
@@ -354,6 +359,19 @@ size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, s
BLI_assert(dst_maxncpy != 0);
BLI_string_debug_size(dst, dst_maxncpy);
char *r_dst = dst;
dst = str_utf8_copy_max_bytes_impl(dst, src, dst_maxncpy - 1);
*dst = '\0';
return size_t(dst - r_dst);
}
size_t BLI_strncpy_utf8_rlen_unterminated(char *__restrict dst,
const char *__restrict src,
size_t dst_maxncpy)
{
BLI_string_debug_size(dst, dst_maxncpy);
char *r_dst = dst;
dst = str_utf8_copy_max_bytes_impl(dst, src, dst_maxncpy);

View File

@@ -3,6 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 */
#include "BLI_string_ref.hh"
#include "BLI_string_utf8_symbols.h"
#include "BLI_vector.hh"
#include "testing/testing.h"
@@ -405,15 +406,56 @@ TEST(string_ref, Substr)
EXPECT_EQ(ref.substr(8, 100), "rld");
}
TEST(string_ref, Copy)
TEST(string_ref, CopyUtf8Truncated)
{
StringRef ref("hello");
char dst[10];
memset(dst, 0xFF, 10);
ref.copy(dst);
EXPECT_EQ(dst[5], '\0');
EXPECT_EQ(dst[6], 0xFF);
EXPECT_EQ(ref, dst);
{
StringRef ref("hello");
char dst[10];
memset(dst, 0xFF, 10);
ref.copy_utf8_truncated(dst);
EXPECT_EQ(dst[5], '\0');
EXPECT_EQ(dst[6], 0xFF);
EXPECT_EQ(ref, dst);
}
{
StringRef ref("0123456789");
char dst[4];
memset(dst, 0xFF, 4);
ref.copy_utf8_truncated(dst);
EXPECT_EQ(dst[0], '0');
EXPECT_EQ(dst[1], '1');
EXPECT_EQ(dst[2], '2');
EXPECT_EQ(dst[3], '\0');
}
{
/* #BLI_STR_UTF8_SUPERSCRIPT_2 is a two-byte code point. */
StringRef ref(BLI_STR_UTF8_SUPERSCRIPT_2 BLI_STR_UTF8_SUPERSCRIPT_2);
{
char dst[1];
ref.copy_utf8_truncated(dst);
EXPECT_EQ(dst[0], '\0');
}
{
char dst[2];
ref.copy_utf8_truncated(dst);
EXPECT_EQ(dst[0], '\0');
}
{
char dst[3];
ref.copy_utf8_truncated(dst);
EXPECT_EQ(StringRef(dst), BLI_STR_UTF8_SUPERSCRIPT_2);
}
{
char dst[4];
ref.copy_utf8_truncated(dst);
EXPECT_EQ(StringRef(dst), BLI_STR_UTF8_SUPERSCRIPT_2);
}
{
char dst[5];
ref.copy_utf8_truncated(dst);
EXPECT_EQ(StringRef(dst), BLI_STR_UTF8_SUPERSCRIPT_2 BLI_STR_UTF8_SUPERSCRIPT_2);
}
}
}
TEST(string_ref, FromStringView)

View File

@@ -214,7 +214,7 @@ class Context : public compositor::Context {
void set_info_message(StringRef message) const override
{
message.copy(info_message_, GPU_INFO_SIZE);
message.copy_utf8_truncated(info_message_, GPU_INFO_SIZE);
}
IDRecalcFlag query_id_recalc_flag(ID *id) const override

View File

@@ -219,7 +219,7 @@ static void init_indexer_entry_from_value(FileIndexerEntry &indexer_entry,
indexer_entry.idcode = GS(idcode_name.data());
idcode_name.substr(2).copy(indexer_entry.datablock_info.name);
idcode_name.substr(2).copy_utf8_truncated(indexer_entry.datablock_info.name);
AssetMetaData *asset_data = BKE_asset_metadata_create();
indexer_entry.datablock_info.asset_data = asset_data;

View File

@@ -300,7 +300,7 @@ static int lookup_or_add_deform_group_index(CurvesGeometry &curves, const String
/* Lazily add the vertex group. */
if (def_nr == -1) {
bDeformGroup *defgroup = MEM_cnew<bDeformGroup>(__func__);
name.copy(defgroup->name);
name.copy_utf8_truncated(defgroup->name);
BLI_addtail(&curves.vertex_group_names, defgroup);
def_nr = BLI_listbase_count(&curves.vertex_group_names) - 1;
BLI_assert(def_nr >= 0);

View File

@@ -4940,7 +4940,7 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali
static void ui_layout_heading_set(uiLayout *layout, const StringRef heading)
{
heading.copy(layout->heading);
heading.copy_utf8_truncated(layout->heading);
}
uiLayout *uiLayoutRow(uiLayout *layout, bool align)

View File

@@ -1545,7 +1545,7 @@ static void copy_vertex_group_names(Mesh &dst_mesh,
continue;
}
bDeformGroup *dst = MEM_cnew<bDeformGroup>(__func__);
src_name.copy(dst->name);
src_name.copy_utf8_truncated(dst->name);
BLI_addtail(&dst_mesh.vertex_group_names, dst);
}
}

View File

@@ -299,7 +299,7 @@ struct GPUSource {
StringRef name = pop_token(line);
GPUFunction *func = MEM_new<GPUFunction>(__func__);
name.copy(func->name, sizeof(func->name));
name.copy_utf8_truncated(func->name, sizeof(func->name));
func->source = reinterpret_cast<void *>(this);
func->totparam = 0;
while (1) {

View File

@@ -212,7 +212,8 @@ void Shader::print_log(Span<StringRefNull> sources,
/* Print the filename the error line is coming from. */
if (!log_item.cursor.file_name_and_error_line.is_empty()) {
char name_buf[256];
log_item.cursor.file_name_and_error_line.substr(0, sizeof(name_buf) - 1).copy(name_buf);
log_item.cursor.file_name_and_error_line.substr(0, sizeof(name_buf) - 1)
.copy_utf8_truncated(name_buf);
BLI_dynstr_appendf(dynstr, "%s%s: %s", info_col, name_buf, reset_col);
}
else if (source_index > 0) {

View File

@@ -304,7 +304,7 @@ int rna_ActionSlot_target_id_type_icon_get(PointerRNA *ptr)
void rna_ActionSlot_name_display_get(PointerRNA *ptr, char *value)
{
animrig::Slot &slot = rna_data_slot(ptr);
slot.identifier_without_prefix().unsafe_copy(value);
slot.identifier_without_prefix().copy_unsafe(value);
}
int rna_ActionSlot_name_display_length(PointerRNA *ptr)

View File

@@ -278,7 +278,7 @@ static void rna_NodeSocket_bl_idname_get(PointerRNA *ptr, char *value)
{
const bNodeSocket *node = static_cast<const bNodeSocket *>(ptr->data);
const blender::bke::bNodeSocketType *ntype = node->typeinfo;
blender::StringRef(ntype->idname).unsafe_copy(value);
blender::StringRef(ntype->idname).copy_unsafe(value);
}
static int rna_NodeSocket_bl_idname_length(PointerRNA *ptr)
@@ -299,7 +299,7 @@ static void rna_NodeSocket_bl_label_get(PointerRNA *ptr, char *value)
{
const bNodeSocket *node = static_cast<const bNodeSocket *>(ptr->data);
const blender::bke::bNodeSocketType *ntype = node->typeinfo;
blender::StringRef(ntype->label).unsafe_copy(value);
blender::StringRef(ntype->label).copy_unsafe(value);
}
static int rna_NodeSocket_bl_label_length(PointerRNA *ptr)
@@ -320,7 +320,7 @@ static void rna_NodeSocket_bl_subtype_label_get(PointerRNA *ptr, char *value)
{
const bNodeSocket *node = static_cast<const bNodeSocket *>(ptr->data);
const blender::bke::bNodeSocketType *ntype = node->typeinfo;
blender::StringRef(ntype->subtype_label).unsafe_copy(value);
blender::StringRef(ntype->subtype_label).copy_unsafe(value);
}
static int rna_NodeSocket_bl_subtype_label_length(PointerRNA *ptr)

View File

@@ -839,7 +839,7 @@ static void rna_Node_bl_idname_get(PointerRNA *ptr, char *value)
{
const bNode *node = static_cast<const bNode *>(ptr->data);
const blender::bke::bNodeType *ntype = node->typeinfo;
blender::StringRef(ntype->idname).unsafe_copy(value);
blender::StringRef(ntype->idname).copy_unsafe(value);
}
static int rna_Node_bl_idname_length(PointerRNA *ptr)
@@ -860,7 +860,7 @@ static void rna_Node_bl_label_get(PointerRNA *ptr, char *value)
{
const bNode *node = static_cast<const bNode *>(ptr->data);
const blender::bke::bNodeType *ntype = node->typeinfo;
blender::StringRef(ntype->ui_name).unsafe_copy(value);
blender::StringRef(ntype->ui_name).copy_unsafe(value);
}
static int rna_Node_bl_label_length(PointerRNA *ptr)
@@ -881,7 +881,7 @@ static void rna_Node_bl_description_get(PointerRNA *ptr, char *value)
{
const bNode *node = static_cast<const bNode *>(ptr->data);
const blender::bke::bNodeType *ntype = node->typeinfo;
blender::StringRef(ntype->ui_description).unsafe_copy(value);
blender::StringRef(ntype->ui_description).copy_unsafe(value);
}
static int rna_Node_bl_description_length(PointerRNA *ptr)
@@ -1495,7 +1495,7 @@ static void rna_NodeTree_bl_idname_get(PointerRNA *ptr, char *value)
{
const bNodeTree *node = static_cast<const bNodeTree *>(ptr->data);
const blender::bke::bNodeTreeType *ntype = node->typeinfo;
blender::StringRef(ntype->idname).unsafe_copy(value);
blender::StringRef(ntype->idname).copy_unsafe(value);
}
static int rna_NodeTree_bl_idname_length(PointerRNA *ptr)
@@ -1516,7 +1516,7 @@ static void rna_NodeTree_bl_label_get(PointerRNA *ptr, char *value)
{
const bNodeTree *node = static_cast<const bNodeTree *>(ptr->data);
const blender::bke::bNodeTreeType *ntype = node->typeinfo;
blender::StringRef(ntype->ui_name).unsafe_copy(value);
blender::StringRef(ntype->ui_name).copy_unsafe(value);
}
static int rna_NodeTree_bl_label_length(PointerRNA *ptr)
@@ -1537,7 +1537,7 @@ static void rna_NodeTree_bl_description_get(PointerRNA *ptr, char *value)
{
const bNodeTree *node = static_cast<const bNodeTree *>(ptr->data);
const blender::bke::bNodeTreeType *ntype = node->typeinfo;
blender::StringRef(ntype->ui_description).unsafe_copy(value);
blender::StringRef(ntype->ui_description).copy_unsafe(value);
}
static int rna_NodeTree_bl_description_length(PointerRNA *ptr)

View File

@@ -188,7 +188,7 @@ void ntreeCompositCryptomatteUpdateLayerNames(bNode *node)
blender::bke::cryptomatte::BKE_cryptomatte_layer_names_get(*session))
{
CryptomatteLayer *layer = MEM_cnew<CryptomatteLayer>(__func__);
layer_name.copy(layer->name);
layer_name.copy_utf8_truncated(layer->name);
BLI_addtail(&n->runtime.layers, layer);
}
}

View File

@@ -699,7 +699,7 @@ void ntree_update_reroute_nodes(bNodeTree *ntree)
const int reroute_index = reroute_nodes[reroute_i];
bNode &reroute_node = *all_nodes[reroute_index];
NodeReroute *storage = static_cast<NodeReroute *>(reroute_node.storage);
StringRef(reroute_type->idname).copy(storage->type_idname);
StringRef(reroute_type->idname).copy_utf8_truncated(storage->type_idname);
nodes::update_node_declaration_and_sockets(*ntree, reroute_node);
}
}