Fix T101803: Max length Operator bl_idname is truncated 1 character.
There were quite a few issues here: * Bad usage of nagic number leading to confusing code * Forgetting to take into accoun final `NULL` char * RNA code thinkin `bl_idname` is python version, when it is actually BL/C version.
This commit is contained in:
parent
4112f0241b
commit
9e77f5f17f
Notes:
blender-bot
2023-02-14 11:21:40 +01:00
Referenced by issue #101803, Max length Operator bl_idname is truncated 1 character
|
@ -364,7 +364,7 @@ typedef struct wmOperatorTypeMacro {
|
|||
struct wmOperatorTypeMacro *next, *prev;
|
||||
|
||||
/* operator id */
|
||||
char idname[64];
|
||||
char idname[64]; /* OP_MAX_TYPENAME */
|
||||
/* rna pointer to access properties, like keymap */
|
||||
/** Operator properties, assigned to ptr->data and can be written to a file. */
|
||||
struct IDProperty *properties;
|
||||
|
@ -551,7 +551,7 @@ typedef struct wmOperator {
|
|||
|
||||
/* saved */
|
||||
/** Used to retrieve type pointer. */
|
||||
char idname[64];
|
||||
char idname[64]; /* OP_MAX_TYPENAME */
|
||||
/** Saved, user-settable properties. */
|
||||
IDProperty *properties;
|
||||
|
||||
|
|
|
@ -1644,12 +1644,7 @@ static StructRNA *rna_MacroOperator_register(Main *bmain,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen(identifier) >= sizeof(dummyop.idname)) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Registering operator class: '%s' is too long, maximum length is %d",
|
||||
identifier,
|
||||
(int)sizeof(dummyop.idname));
|
||||
if (!WM_operator_py_idname_ok_or_report(reports, identifier, dummyot.idname)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1661,10 +1656,6 @@ static StructRNA *rna_MacroOperator_register(Main *bmain,
|
|||
}
|
||||
}
|
||||
|
||||
if (!WM_operator_py_idname_ok_or_report(reports, identifier, dummyot.idname)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char idname_conv[sizeof(dummyop.idname)];
|
||||
WM_operator_bl_idname(idname_conv, dummyot.idname); /* convert the idname from python */
|
||||
|
||||
|
@ -1867,8 +1858,9 @@ static void rna_def_operator_common(StructRNA *srna)
|
|||
/* Registration */
|
||||
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "type->idname");
|
||||
/* Without setting the length the pointer size would be used. -3 because `.` -> `_OT_`. */
|
||||
RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME - 3);
|
||||
/* String stored here is the 'BL' identifier (`OPMODULE_OT_my_op`),
|
||||
* not the 'python' identifier (`opmodule.my_op`). */
|
||||
RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME);
|
||||
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_idname_set");
|
||||
// RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_flag(prop, PROP_REGISTER);
|
||||
|
|
|
@ -107,19 +107,32 @@
|
|||
/** \name Operator API
|
||||
* \{ */
|
||||
|
||||
#define OP_BL_SEP_STRING "_OT_"
|
||||
#define OP_BL_SEP_LEN 4
|
||||
|
||||
#define OP_PY_SEP_CHAR '.'
|
||||
#define OP_PY_SEP_LEN 1
|
||||
|
||||
/* Difference between python 'identifier' and BL/C code one ("." separator replaced by "_OT_"),
|
||||
* and final `\0` char. */
|
||||
#define OP_MAX_PY_IDNAME (OP_MAX_TYPENAME - OP_BL_SEP_LEN + OP_PY_SEP_LEN - 1)
|
||||
|
||||
size_t WM_operator_py_idname(char *dst, const char *src)
|
||||
{
|
||||
const char *sep = strstr(src, "_OT_");
|
||||
const char *sep = strstr(src, OP_BL_SEP_STRING);
|
||||
if (sep) {
|
||||
int ofs = (sep - src);
|
||||
const size_t sep_offset = (size_t)(sep - src);
|
||||
|
||||
/* NOTE: we use ascii `tolower` instead of system `tolower`, because the
|
||||
* latter depends on the locale, and can lead to `idname` mismatch. */
|
||||
memcpy(dst, src, sizeof(char) * ofs);
|
||||
BLI_str_tolower_ascii(dst, ofs);
|
||||
memcpy(dst, src, sep_offset);
|
||||
BLI_str_tolower_ascii(dst, sep_offset);
|
||||
|
||||
dst[ofs] = '.';
|
||||
return BLI_strncpy_rlen(dst + (ofs + 1), sep + 4, OP_MAX_TYPENAME - (ofs + 1)) + (ofs + 1);
|
||||
dst[sep_offset] = OP_PY_SEP_CHAR;
|
||||
return BLI_strncpy_rlen(dst + (sep_offset + OP_PY_SEP_LEN),
|
||||
sep + OP_BL_SEP_LEN,
|
||||
OP_MAX_TYPENAME - sep_offset - OP_PY_SEP_LEN) +
|
||||
(sep_offset + OP_PY_SEP_LEN);
|
||||
}
|
||||
/* Should not happen but support just in case. */
|
||||
return BLI_strncpy_rlen(dst, src, OP_MAX_TYPENAME);
|
||||
|
@ -127,15 +140,19 @@ size_t WM_operator_py_idname(char *dst, const char *src)
|
|||
|
||||
size_t WM_operator_bl_idname(char *dst, const char *src)
|
||||
{
|
||||
const char *sep = strchr(src, '.');
|
||||
int from_len;
|
||||
if (sep && (from_len = strlen(src)) < OP_MAX_TYPENAME - 3) {
|
||||
const int ofs = (sep - src);
|
||||
memcpy(dst, src, sizeof(char) * ofs);
|
||||
BLI_str_toupper_ascii(dst, ofs);
|
||||
memcpy(dst + ofs, "_OT_", 4);
|
||||
memcpy(dst + (ofs + 4), sep + 1, (from_len - ofs));
|
||||
return (from_len - ofs) - 1;
|
||||
const size_t from_len = (size_t)strlen(src);
|
||||
|
||||
const char *sep = strchr(src, OP_PY_SEP_CHAR);
|
||||
if (sep && (from_len <= OP_MAX_PY_IDNAME)) {
|
||||
const size_t sep_offset = (size_t)(sep - src);
|
||||
memcpy(dst, src, sep_offset);
|
||||
BLI_str_toupper_ascii(dst, sep_offset);
|
||||
|
||||
memcpy(dst + sep_offset, OP_BL_SEP_STRING, OP_BL_SEP_LEN);
|
||||
BLI_strncpy(dst + sep_offset + OP_BL_SEP_LEN,
|
||||
sep + OP_PY_SEP_LEN,
|
||||
from_len - sep_offset - OP_PY_SEP_LEN + 1);
|
||||
return from_len + OP_BL_SEP_LEN - OP_PY_SEP_LEN;
|
||||
}
|
||||
/* Should not happen but support just in case. */
|
||||
return BLI_strncpy_rlen(dst, src, OP_MAX_TYPENAME);
|
||||
|
@ -166,14 +183,14 @@ bool WM_operator_py_idname_ok_or_report(ReportList *reports,
|
|||
}
|
||||
}
|
||||
|
||||
if (i > (MAX_NAME - 3)) {
|
||||
if (i > OP_MAX_PY_IDNAME) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Registering operator class: '%s', invalid bl_idname '%s', "
|
||||
"is too long, maximum length is %d",
|
||||
classname,
|
||||
idname,
|
||||
MAX_NAME - 3);
|
||||
OP_MAX_PY_IDNAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue