BLI_string: remove potentially unsafe BLI_sprintf

Replace by BLI_snprintf or string joining.

See #108917.
This commit is contained in:
Campbell Barton
2023-06-25 13:31:08 +10:00
parent 85029da289
commit f4a65cfe5d
12 changed files with 206 additions and 145 deletions

View File

@@ -3635,12 +3635,12 @@ void BKE_image_set_filepath_from_tile_number(char *filepath,
}
if (tile_format == UDIM_TILE_FORMAT_UDIM) {
BLI_sprintf(filepath, pattern, tile_number);
BLI_snprintf(filepath, FILE_MAX, pattern, tile_number);
}
else if (tile_format == UDIM_TILE_FORMAT_UVTILE) {
int u = ((tile_number - 1001) % 10);
int v = ((tile_number - 1001) / 10);
BLI_sprintf(filepath, pattern, u + 1, v + 1);
BLI_snprintf(filepath, FILE_MAX, pattern, u + 1, v + 1);
}
}

View File

@@ -3133,19 +3133,23 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_laye
BKE_ptcache_bake(&baker);
}
static void ptcache_dt_to_str(char *str, double dtime)
static void ptcache_dt_to_str(char *str, size_t str_maxncpy, double dtime)
{
if (dtime > 60.0) {
if (dtime > 3600.0) {
BLI_sprintf(
str, "%ih %im %is", (int)(dtime / 3600), (int)(dtime / 60) % 60, ((int)dtime) % 60);
BLI_snprintf(str,
str_maxncpy,
"%ih %im %is",
(int)(dtime / 3600),
(int)(dtime / 60) % 60,
((int)dtime) % 60);
}
else {
BLI_sprintf(str, "%im %is", (int)(dtime / 60) % 60, ((int)dtime) % 60);
BLI_snprintf(str, str_maxncpy, "%im %is", (int)(dtime / 60) % 60, ((int)dtime) % 60);
}
}
else {
BLI_sprintf(str, "%is", ((int)dtime) % 60);
BLI_snprintf(str, str_maxncpy, "%is", ((int)dtime) % 60);
}
}
@@ -3300,9 +3304,9 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
if (use_timer || fetd > 60.0) {
use_timer = true;
ptcache_dt_to_str(cur, ctime - ptime);
ptcache_dt_to_str(run, ctime - stime);
ptcache_dt_to_str(etd, fetd);
ptcache_dt_to_str(cur, sizeof(cur), ctime - ptime);
ptcache_dt_to_str(run, sizeof(run), ctime - stime);
ptcache_dt_to_str(etd, sizeof(etd), fetd);
printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r",
run,
@@ -3325,7 +3329,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
if (use_timer) {
/* start with newline because of \r above */
ptcache_dt_to_str(run, PIL_check_seconds_timer() - stime);
ptcache_dt_to_str(run, sizeof(run), PIL_check_seconds_timer() - stime);
printf("\nBake %s %s (%i frames simulated).\n",
(cancel ? "canceled after" : "finished in"),
run,

View File

@@ -243,14 +243,6 @@ size_t BLI_vsnprintf_rlen(char *__restrict dst,
char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2);
/**
* A wrapper around `::sprintf()` which does not generate security warnings.
*
* \note Use #BLI_snprintf for cases when the string size is known.
*/
int BLI_sprintf(char *__restrict str, const char *__restrict format, ...) ATTR_NONNULL(1, 2)
ATTR_PRINTF_FORMAT(2, 3);
/**
* This roughly matches C and Python's string escaping with double quotes - `"`.
*

View File

@@ -118,6 +118,9 @@ bool BLI_uniquename(struct ListBase *list,
/* Expand array functions. */
size_t BLI_string_len_array(const char *strings[], uint strings_num) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
/* Intentionally no comma after `_BLI_STRING_ARGS_0` to allow it to be empty. */
#define _BLI_STRING_ARGS_1 _BLI_STRING_ARGS_0 const char *a
#define _BLI_STRING_ARGS_2 _BLI_STRING_ARGS_1, const char *b

View File

@@ -244,17 +244,6 @@ char *BLI_sprintfN(const char *__restrict format, ...)
return n;
}
int BLI_sprintf(char *__restrict str, const char *__restrict format, ...)
{
va_list arg;
va_start(arg, format);
const int result = vsprintf(str, format, arg);
va_end(arg);
return result;
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -357,6 +357,15 @@ bool BLI_uniquename(ListBase *list,
name_maxncpy);
}
size_t BLI_string_len_array(const char *strings[], uint strings_num)
{
size_t total_len = 0;
for (uint i = 0; i < strings_num; i++) {
total_len += strlen(strings[i]);
}
return total_len;
}
/* ------------------------------------------------------------------------- */
/** \name Join Strings
*
@@ -411,11 +420,8 @@ size_t BLI_string_join_array_by_sep_char(
char *BLI_string_join_arrayN(const char *strings[], uint strings_num)
{
uint total_len = 1;
for (uint i = 0; i < strings_num; i++) {
total_len += strlen(strings[i]);
}
char *result = MEM_mallocN(sizeof(char) * total_len, __func__);
const uint result_size = BLI_string_len_array(strings, strings_num) + 1;
char *result = MEM_mallocN(sizeof(char) * result_size, __func__);
char *c = result;
for (uint i = 0; i < strings_num; i++) {
const size_t string_len = strlen(strings[i]);
@@ -424,20 +430,21 @@ char *BLI_string_join_arrayN(const char *strings[], uint strings_num)
}
/* Only needed when `strings_num == 0`. */
*c = '\0';
BLI_assert(result + result_size == c + 1);
return result;
}
char *BLI_string_join_array_by_sep_charN(char sep, const char *strings[], uint strings_num)
{
uint total_len = 0;
uint result_size = 0;
for (uint i = 0; i < strings_num; i++) {
total_len += strlen(strings[i]) + 1;
result_size += strlen(strings[i]) + 1;
}
if (total_len == 0) {
total_len = 1;
if (result_size == 0) {
result_size = 1;
}
char *result = MEM_mallocN(sizeof(char) * total_len, __func__);
char *result = MEM_mallocN(sizeof(char) * result_size, __func__);
char *c = result;
if (strings_num != 0) {
for (uint i = 0; i < strings_num; i++) {
@@ -450,6 +457,7 @@ char *BLI_string_join_array_by_sep_charN(char sep, const char *strings[], uint s
c--;
}
*c = '\0';
BLI_assert(result + result_size == c + 1);
return result;
}
@@ -458,15 +466,15 @@ char *BLI_string_join_array_by_sep_char_with_tableN(char sep,
const char *strings[],
uint strings_num)
{
uint total_len = 0;
uint result_size = 0;
for (uint i = 0; i < strings_num; i++) {
total_len += strlen(strings[i]) + 1;
result_size += strlen(strings[i]) + 1;
}
if (total_len == 0) {
total_len = 1;
if (result_size == 0) {
result_size = 1;
}
char *result = MEM_mallocN(sizeof(char) * total_len, __func__);
char *result = MEM_mallocN(sizeof(char) * result_size, __func__);
char *c = result;
if (strings_num != 0) {
for (uint i = 0; i < strings_num; i++) {
@@ -481,6 +489,7 @@ char *BLI_string_join_array_by_sep_char_with_tableN(char sep,
c--;
}
*c = '\0';
BLI_assert(result + result_size == c + 1);
return result;
}

View File

@@ -88,19 +88,25 @@ bool BLI_uuid_equal(const bUUID uuid1, const bUUID uuid2)
void BLI_uuid_format(char *buffer, const bUUID uuid)
{
BLI_sprintf(buffer,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
uuid.time_low,
uuid.time_mid,
uuid.time_hi_and_version,
uuid.clock_seq_hi_and_reserved,
uuid.clock_seq_low,
uuid.node[0],
uuid.node[1],
uuid.node[2],
uuid.node[3],
uuid.node[4],
uuid.node[5]);
const size_t buffer_len_unclamped = BLI_snprintf(
buffer,
UUID_STRING_LEN,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
uuid.time_low,
uuid.time_mid,
uuid.time_hi_and_version,
uuid.clock_seq_hi_and_reserved,
uuid.clock_seq_low,
uuid.node[0],
uuid.node[1],
uuid.node[2],
uuid.node[3],
uuid.node[4],
uuid.node[5]);
/* Assert the string length is not clamped. */
BLI_assert(buffer_len_unclamped == UUID_STRING_LEN - 1);
UNUSED_VARS_NDEBUG(buffer_len_unclamped);
}
bool BLI_uuid_parse_string(bUUID *uuid, const char *buffer)

View File

@@ -15,6 +15,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_string_utils.h"
#include "BLI_threads.h"
#include "BLI_timecode.h"
#include "BLI_utildefines.h"
@@ -402,17 +403,25 @@ static void render_freejob(void *rjv)
MEM_freeN(rj);
}
/* str is IMA_MAX_RENDER_TEXT in size */
static void make_renderinfo_string(const RenderStats *rs,
const Scene *scene,
const bool v3d_override,
const char *error,
char *str)
char ret[IMA_MAX_RENDER_TEXT])
{
char info_time_str[32]; /* used to be extern to header_info.c */
const char *info_space = " ";
const char *info_sep = "| ";
struct {
char time_last[32];
char time_elapsed[32];
char frame[16];
char statistics[64];
} info_buffers;
uintptr_t mem_in_use, peak_memory;
float megs_used_memory, megs_peak_memory;
char *spos = str;
const char *ret_array[32];
int i = 0;
mem_in_use = MEM_get_memory_in_use();
peak_memory = MEM_get_peak_memory();
@@ -422,65 +431,96 @@ static void make_renderinfo_string(const RenderStats *rs,
/* local view */
if (rs->localview) {
spos += BLI_sprintf(spos, "%s | ", TIP_("3D Local View"));
ret_array[i++] = TIP_("3D Local View ");
ret_array[i++] = info_sep;
}
else if (v3d_override) {
spos += BLI_sprintf(spos, "%s | ", TIP_("3D View"));
ret_array[i++] = TIP_("3D View ");
ret_array[i++] = info_sep;
}
/* frame number */
spos += BLI_sprintf(spos, TIP_("Frame:%d "), (scene->r.cfra));
SNPRINTF(info_buffers.frame, "%d ", scene->r.cfra);
ret_array[i++] = TIP_("Frame:");
ret_array[i++] = info_buffers.frame;
/* previous and elapsed time */
BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), rs->lastframetime);
/* Previous and elapsed time. */
const char *info_time = info_buffers.time_last;
BLI_timecode_string_from_time_simple(
info_buffers.time_last, sizeof(info_buffers.time_last), rs->lastframetime);
ret_array[i++] = info_sep;
if (rs->infostr && rs->infostr[0]) {
if (rs->lastframetime != 0.0) {
spos += BLI_sprintf(spos, TIP_("| Last:%s "), info_time_str);
ret_array[i++] = "Last:";
ret_array[i++] = info_buffers.time_last;
ret_array[i++] = info_space;
}
info_time = info_buffers.time_elapsed;
BLI_timecode_string_from_time_simple(info_buffers.time_elapsed,
sizeof(info_buffers.time_elapsed),
PIL_check_seconds_timer() - rs->starttime);
}
ret_array[i++] = TIP_("Time:");
ret_array[i++] = info_time;
ret_array[i++] = info_space;
/* Statistics. */
{
const char *info_statistics = nullptr;
if (rs->statstr) {
if (rs->statstr[0]) {
info_statistics = rs->statstr;
}
}
else {
spos += BLI_sprintf(spos, "| ");
if (rs->mem_peak == 0.0f) {
SNPRINTF(info_buffers.statistics,
TIP_("Mem:%.2fM (Peak %.2fM)"),
megs_used_memory,
megs_peak_memory);
}
else {
SNPRINTF(
info_buffers.statistics, TIP_("Mem:%.2fM, Peak: %.2fM"), rs->mem_used, rs->mem_peak);
}
info_statistics = info_buffers.statistics;
}
BLI_timecode_string_from_time_simple(
info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime);
}
else {
spos += BLI_sprintf(spos, "| ");
}
spos += BLI_sprintf(spos, TIP_("Time:%s "), info_time_str);
/* statistics */
if (rs->statstr) {
if (rs->statstr[0]) {
spos += BLI_sprintf(spos, "| %s ", rs->statstr);
}
}
else {
if (rs->mem_peak == 0.0f) {
spos += BLI_sprintf(
spos, TIP_("| Mem:%.2fM (Peak %.2fM) "), megs_used_memory, megs_peak_memory);
}
else {
spos += BLI_sprintf(spos, TIP_("| Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak);
if (info_statistics) {
ret_array[i++] = info_sep;
ret_array[i++] = info_statistics;
ret_array[i++] = info_space;
}
}
/* extra info */
if (rs->infostr && rs->infostr[0]) {
spos += BLI_sprintf(spos, "| %s ", rs->infostr);
}
else if (error && error[0]) {
spos += BLI_sprintf(spos, "| %s ", error);
/* Extra info. */
{
const char *info_extra = nullptr;
if (rs->infostr && rs->infostr[0]) {
info_extra = rs->infostr;
}
else if (error && error[0]) {
info_extra = error;
}
if (info_extra) {
ret_array[i++] = info_sep;
ret_array[i++] = info_extra;
ret_array[i++] = info_space;
}
}
/* very weak... but 512 characters is quite safe */
if (spos >= str + IMA_MAX_RENDER_TEXT) {
if (G.debug & G_DEBUG) {
if (G.debug & G_DEBUG) {
if (BLI_string_len_array(ret_array, i) >= IMA_MAX_RENDER_TEXT) {
printf("WARNING! renderwin text beyond limit\n");
}
}
BLI_assert(i < int(BOUNDED_ARRAY_TYPE_SIZE<decltype(ret_array)>()));
BLI_string_join_array(ret, IMA_MAX_RENDER_TEXT, ret_array, i);
}
static void image_renderinfo_cb(void *rjv, RenderStats *rs)

View File

@@ -1168,7 +1168,9 @@ static void rna_ParticleSystem_active_particle_target_index_set(struct PointerRN
}
}
static void rna_ParticleTarget_name_get(PointerRNA *ptr, char *value)
static size_t rna_ParticleTarget_name_get_impl(PointerRNA *ptr,
char *value,
const size_t value_maxncpy)
{
ParticleTarget *pt = ptr->data;
@@ -1184,29 +1186,32 @@ static void rna_ParticleTarget_name_get(PointerRNA *ptr, char *value)
}
if (psys) {
int value_len;
if (pt->ob) {
BLI_sprintf(value, "%s: %s", pt->ob->id.name + 2, psys->name);
value_len = BLI_snprintf_rlen(
value, value_maxncpy, "%s: %s", pt->ob->id.name + 2, psys->name);
}
else {
strcpy(value, psys->name);
value_len = BLI_strncpy_rlen(value, psys->name, value_maxncpy);
}
}
else {
strcpy(value, TIP_("Invalid target!"));
return value_len;
}
}
else {
strcpy(value, TIP_("Invalid target!"));
}
return BLI_strncpy_rlen(value, TIP_("Invalid target!"), value_maxncpy);
}
static void rna_ParticleTarget_name_get(PointerRNA *ptr, char *value)
{
char value_buf[MAX_ID_NAME + MAX_ID_NAME + 64];
const size_t value_buf_len = rna_ParticleTarget_name_get_impl(ptr, value_buf, sizeof(value_buf));
memcpy(value, value_buf, value_buf_len + 1);
}
static int rna_ParticleTarget_name_length(PointerRNA *ptr)
{
char tvalue[MAX_ID_NAME + MAX_ID_NAME + 64];
rna_ParticleTarget_name_get(ptr, tvalue);
return strlen(tvalue);
char value_buf[MAX_ID_NAME + MAX_ID_NAME + 64];
return rna_ParticleTarget_name_get_impl(ptr, value_buf, sizeof(value_buf));
}
static int particle_id_check(const PointerRNA *ptr)
@@ -1304,7 +1309,9 @@ static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int
}
}
static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *value)
static size_t rna_ParticleDupliWeight_name_get_impl(PointerRNA *ptr,
char *value,
const size_t value_maxncpy)
{
ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
psys_find_group_weights(part);
@@ -1312,20 +1319,24 @@ static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *value)
ParticleDupliWeight *dw = ptr->data;
if (dw->ob) {
BLI_sprintf(value, "%s: %i", dw->ob->id.name + 2, dw->count);
}
else {
strcpy(value, "No object");
return BLI_snprintf_rlen(value, value_maxncpy, "%s: %i", dw->ob->id.name + 2, dw->count);
}
return BLI_strncpy_rlen(value, "No object", value_maxncpy);
}
static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *value)
{
char value_buf[MAX_ID_NAME + 64];
const size_t value_buf_len = rna_ParticleDupliWeight_name_get_impl(
ptr, value_buf, sizeof(value_buf));
memcpy(value, value_buf, value_buf_len + 1);
}
static int rna_ParticleDupliWeight_name_length(PointerRNA *ptr)
{
char tvalue[MAX_ID_NAME + 64];
rna_ParticleDupliWeight_name_get(ptr, tvalue);
return strlen(tvalue);
char value_buf[MAX_ID_NAME + 64];
return rna_ParticleDupliWeight_name_get_impl(ptr, value_buf, sizeof(value_buf));
}
static const EnumPropertyItem *rna_Particle_type_itemf(bContext *UNUSED(C),

View File

@@ -84,7 +84,8 @@ static void unique_name(bNode *node)
STRNCPY(new_name, name);
name = new_name;
}
BLI_sprintf(new_name + new_len - 4, ".%03d", ++suffix);
int name_ofs = new_len - 4;
BLI_snprintf(new_name + name_ofs, sizeof(new_name) - name_ofs, ".%03d", ++suffix);
}
if (new_name[0] != '\0') {

View File

@@ -9,6 +9,7 @@
#include "BLI_math.h"
#include "BLI_sort.h"
#include "BLI_string.h"
#include "BLI_string_utils.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
@@ -4255,22 +4256,24 @@ int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype)
char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32])
{
/* zero to ensure string is always NULL terminated */
char *ret_ptr = ret;
const char *ret_array[4];
int i = 0;
if (htype & BM_VERT) {
ret_ptr += BLI_sprintf(ret_ptr, "/%s", BPy_BMVert_Type.tp_name);
ret_array[i++] = BPy_BMVert_Type.tp_name;
}
if (htype & BM_EDGE) {
ret_ptr += BLI_sprintf(ret_ptr, "/%s", BPy_BMEdge_Type.tp_name);
ret_array[i++] = BPy_BMEdge_Type.tp_name;
}
if (htype & BM_FACE) {
ret_ptr += BLI_sprintf(ret_ptr, "/%s", BPy_BMFace_Type.tp_name);
ret_array[i++] = BPy_BMFace_Type.tp_name;
}
if (htype & BM_LOOP) {
ret_ptr += BLI_sprintf(ret_ptr, "/%s", BPy_BMLoop_Type.tp_name);
ret_array[i++] = BPy_BMLoop_Type.tp_name;
}
ret[0] = '(';
*ret_ptr++ = ')';
*ret_ptr = '\0';
int ret_ofs = BLI_string_join_array_by_sep_char(ret + 1, 30, '/', ret_array, i) + 1;
ret[ret_ofs] = ')';
ret[ret_ofs + 1] = '\0';
return ret;
}
char *BPy_BMElem_StringFromHType(const char htype)

View File

@@ -969,7 +969,8 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self)
PointerRNA ptr;
const char *name;
const char *type_id = NULL;
char type_fmt[64] = "";
char type_lower[64];
char type_count[16];
int type;
PYRNA_PROP_CHECK_OBJ(self);
@@ -982,13 +983,10 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self)
return NULL;
}
/* This should never fail. */
STRNCPY(type_lower, type_id);
BLI_str_tolower_ascii(type_lower, sizeof(type_lower));
int len = -1;
char *c = type_fmt;
while ((*c++ = tolower(*type_id++))) {
}
if (type == PROP_COLLECTION) {
len = pyrna_prop_collection_length(self);
}
@@ -997,7 +995,10 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self)
}
if (len != -1) {
BLI_sprintf(--c, "[%d]", len);
SNPRINTF(type_count, "[%d]", len);
}
else {
type_count[0] = '\0';
}
/* If a pointer, try to print name of pointer target too. */
@@ -1006,8 +1007,9 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self)
name = RNA_struct_name_get_alloc(&ptr, NULL, 0, NULL);
if (name) {
ret = PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s(\"%.200s\")>",
type_fmt,
ret = PyUnicode_FromFormat("<bpy_%.200s%.200s, %.200s.%.200s(\"%.200s\")>",
type_lower,
type_count,
RNA_struct_identifier(self->ptr.type),
RNA_property_identifier(self->prop),
name);
@@ -1019,12 +1021,13 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self)
PointerRNA r_ptr;
if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) {
return PyUnicode_FromFormat(
"<bpy_%.200s, %.200s>", type_fmt, RNA_struct_identifier(r_ptr.type));
"<bpy_%.200s%.200s, %.200s>", type_lower, type_count, RNA_struct_identifier(r_ptr.type));
}
}
return PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s>",
type_fmt,
return PyUnicode_FromFormat("<bpy_%.200s%.200s, %.200s.%.200s>",
type_lower,
type_count,
RNA_struct_identifier(self->ptr.type),
RNA_property_identifier(self->prop));
}