[Bf-blender-cvs] [9e77f5f17fc] master: Fix T101803: Max length Operator bl_idname is truncated 1 character.

Bastien Montagne noreply at git.blender.org
Fri Oct 14 18:38:00 CEST 2022


Commit: 9e77f5f17fcadf12316ed855ac47abf32592d84f
Author: Bastien Montagne
Date:   Fri Oct 14 18:35:28 2022 +0200
Branches: master
https://developer.blender.org/rB9e77f5f17fcadf12316ed855ac47abf32592d84f

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.

===================================================================

M	source/blender/makesdna/DNA_windowmanager_types.h
M	source/blender/makesrna/intern/rna_wm.c
M	source/blender/windowmanager/intern/wm_operators.c

===================================================================

diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index d57cca0b055..9b235fac049 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -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;
 
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 7fd590005fd..5b5544120a1 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -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);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 58791dbd00a..fa89e7a4caa 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -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;
   }



More information about the Bf-blender-cvs mailing list