[Bf-blender-cvs] [31e6f0dc7af] master: makesdna: fix parsing 'const', 'struct', 'unsigned' as a prefix

Campbell Barton noreply at git.blender.org
Wed Jul 7 04:37:19 CEST 2021


Commit: 31e6f0dc7af6ff1be19da93021b7095fe68da833
Author: Campbell Barton
Date:   Wed Jul 7 12:35:03 2021 +1000
Branches: master
https://developer.blender.org/rB31e6f0dc7af6ff1be19da93021b7095fe68da833

makesdna: fix parsing 'const', 'struct', 'unsigned' as a prefix

DNA parsing assumed any identifier which starts with
(`struct`, `unsigned`, `const`) was that identifier.

So a struct called `constTest foo;` would be parsed as `est foo;`.

Add utility function to check identifiers are not
part of a larger identifier.

This also supports skipping these identifiers in any order.

Reviewed By: LazyDodo

Ref D11837

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

M	source/blender/makesdna/intern/makesdna.c

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

diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index fb1cf9b591d..f2a75a60a44 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -43,6 +43,7 @@
 
 #define DNA_DEPRECATED_ALLOW
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -272,6 +273,37 @@ void print_struct_sizes(void);
  * Make DNA string (write to file).
  * \{ */
 
+static bool match_identifier_with_len(const char *str,
+                                      const char *identifier,
+                                      const size_t identifier_len)
+{
+  if (strncmp(str, identifier, identifier_len) == 0) {
+    /* Check `str` isn't a prefix to a longer identifier. */
+    if (isdigit(str[identifier_len]) || isalpha(str[identifier_len]) ||
+        (str[identifier_len] == '_')) {
+      return false;
+    }
+    return true;
+  }
+  return false;
+}
+
+static bool match_identifier(const char *str, const char *identifier)
+{
+  const size_t identifier_len = strlen(identifier);
+  return match_identifier_with_len(str, identifier, identifier_len);
+}
+
+static bool match_identifier_and_advance(char **str_ptr, const char *identifier)
+{
+  const size_t identifier_len = strlen(identifier);
+  if (match_identifier_with_len(*str_ptr, identifier, identifier_len)) {
+    (*str_ptr) += identifier_len;
+    return true;
+  }
+  return false;
+}
+
 static const char *version_struct_static_from_alias(const char *str)
 {
   const char *str_test = BLI_ghash_lookup(g_version_data.struct_map_static_from_alias, str);
@@ -619,7 +651,7 @@ static int preprocess_include(char *maindata, const int maindata_len)
     else if (cp[-1] == '*' && cp[0] == ' ') {
       /* pointers with a space */
     } /* skip special keywords */
-    else if (strncmp("DNA_DEPRECATED", cp, 14) == 0) {
+    else if (match_identifier(cp, "DNA_DEPRECATED")) {
       /* single values are skipped already, so decrement 1 less */
       a -= 13;
       cp += 13;
@@ -721,7 +753,7 @@ static int convert_include(const char *filename)
         md1++;
 
         /* we've got a struct name when... */
-        if (strncmp(md1 - 7, "struct", 6) == 0) {
+        if (match_identifier(md1 - 7, "struct")) {
 
           const int strct = add_type(md1, 0);
           if (strct == -1) {
@@ -756,14 +788,22 @@ static int convert_include(const char *filename)
 
             /* skip when it says 'struct' or 'unsigned' or 'const' */
             if (*md1) {
-              if (strncmp(md1, "struct", 6) == 0) {
-                md1 += 7;
-              }
-              if (strncmp(md1, "unsigned", 8) == 0) {
-                md1 += 9;
-              }
-              if (strncmp(md1, "const", 5) == 0) {
-                md1 += 6;
+              const char *md1_prev = md1;
+              while (match_identifier_and_advance(&md1, "struct") ||
+                     match_identifier_and_advance(&md1, "unsigned") ||
+                     match_identifier_and_advance(&md1, "const")) {
+                if (UNLIKELY(!ELEM(*md1, '\0', ' '))) {
+                  /* This will happen with: `unsigned(*value)[3]` which isn't supported. */
+                  fprintf(stderr,
+                          "File '%s' contains non white space character "
+                          "\"%c\" after identifier \"%s\"\n",
+                          filename,
+                          *md1,
+                          md1_prev);
+                  return 1;
+                }
+                /* Skip ' ' or '\0'. */
+                md1++;
               }
 
               /* we've got a type! */



More information about the Bf-blender-cvs mailing list