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:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user