[Bf-blender-cvs] [78f61bf8c13] blender-v3.2-release: Fix T97906: OpenEXR files with lower case xyz channel names not read correctly

Brecht Van Lommel noreply at git.blender.org
Mon May 9 18:30:26 CEST 2022


Commit: 78f61bf8c13460f8065eaa8eabaa2ac5a4c66a5e
Author: Brecht Van Lommel
Date:   Mon May 9 17:17:03 2022 +0200
Branches: blender-v3.2-release
https://developer.blender.org/rB78f61bf8c13460f8065eaa8eabaa2ac5a4c66a5e

Fix T97906: OpenEXR files with lower case xyz channel names not read correctly

Adds some utility functions to avoid using toupper() which depends on the
locale and should not be used for this type of parsing.

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

M	source/blender/blenlib/BLI_string.h
M	source/blender/blenlib/intern/string.c
M	source/blender/imbuf/intern/openexr/openexr_api.cpp

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

diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 45abac33795..0344622e81d 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -343,8 +343,16 @@ int BLI_strcmp_ignore_pad(const char *str1, const char *str2, char pad) ATTR_WAR
  */
 size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 
+/**
+ * String case conversion, not affected by locale.
+ */
+
 void BLI_str_tolower_ascii(char *str, size_t len) ATTR_NONNULL();
 void BLI_str_toupper_ascii(char *str, size_t len) ATTR_NONNULL();
+
+char BLI_tolower_ascii(const char c);
+char BLI_toupper_ascii(const char c);
+
 /**
  * Strip white-space from end of the string.
  */
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 74559751d91..8387eb5f4f9 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -914,14 +914,22 @@ size_t BLI_strnlen(const char *s, const size_t maxlen)
 /** \name String Case Conversion
  * \{ */
 
+char BLI_tolower_ascii(const char c)
+{
+  return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
+}
+
+char BLI_toupper_ascii(const char c)
+{
+  return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
+}
+
 void BLI_str_tolower_ascii(char *str, const size_t len)
 {
   size_t i;
 
   for (i = 0; (i < len) && str[i]; i++) {
-    if (str[i] >= 'A' && str[i] <= 'Z') {
-      str[i] += 'a' - 'A';
-    }
+    str[i] = BLI_tolower_ascii(str[i]);
   }
 }
 
@@ -930,9 +938,7 @@ void BLI_str_toupper_ascii(char *str, const size_t len)
   size_t i;
 
   for (i = 0; (i < len) && str[i]; i++) {
-    if (str[i] >= 'a' && str[i] <= 'z') {
-      str[i] -= 'a' - 'A';
-    }
+    str[i] = BLI_toupper_ascii(str[i]);
   }
 }
 
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 9948aaac5da..2281d8d85b3 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -1394,12 +1394,10 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
   const char *name = echan->m->name.c_str();
   const char *end = name + strlen(name);
   const char *token;
-  char tokenbuf[EXR_TOT_MAXNAME];
-  int len;
 
   /* some multilayers have the combined buffer with names A B G R saved */
   if (name[1] == 0) {
-    echan->chan_id = name[0];
+    echan->chan_id = BLI_toupper_ascii(name[0]);
     layname[0] = '\0';
 
     if (ELEM(name[0], 'R', 'G', 'B', 'A')) {
@@ -1416,13 +1414,17 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
   }
 
   /* last token is channel identifier */
-  len = imb_exr_split_token(name, end, &token);
+  size_t len = imb_exr_split_token(name, end, &token);
   if (len == 0) {
     printf("multilayer read: bad channel name: %s\n", name);
     return 0;
   }
+
+  char channelname[EXR_TOT_MAXNAME];
+  BLI_strncpy(channelname, token, std::min(len + 1, sizeof(channelname)));
+
   if (len == 1) {
-    echan->chan_id = token[0];
+    echan->chan_id = BLI_toupper_ascii(channelname[0]);
   }
   else if (len > 1) {
     bool ok = false;
@@ -1436,36 +1438,35 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
        *
        * Here we do some magic to distinguish such cases.
        */
-      if (ELEM(token[1], 'X', 'Y', 'Z') || ELEM(token[1], 'R', 'G', 'B') ||
-          ELEM(token[1], 'U', 'V', 'A')) {
-        echan->chan_id = token[1];
+      const char chan_id = BLI_toupper_ascii(channelname[1]);
+      if (ELEM(chan_id, 'X', 'Y', 'Z', 'R', 'G', 'B', 'U', 'V', 'A')) {
+        echan->chan_id = chan_id;
         ok = true;
       }
     }
-    else if (BLI_strcaseeq(token, "red")) {
+    else if (BLI_strcaseeq(channelname, "red")) {
       echan->chan_id = 'R';
       ok = true;
     }
-    else if (BLI_strcaseeq(token, "green")) {
+    else if (BLI_strcaseeq(channelname, "green")) {
       echan->chan_id = 'G';
       ok = true;
     }
-    else if (BLI_strcaseeq(token, "blue")) {
+    else if (BLI_strcaseeq(channelname, "blue")) {
       echan->chan_id = 'B';
       ok = true;
     }
-    else if (BLI_strcaseeq(token, "alpha")) {
+    else if (BLI_strcaseeq(channelname, "alpha")) {
       echan->chan_id = 'A';
       ok = true;
     }
-    else if (BLI_strcaseeq(token, "depth")) {
+    else if (BLI_strcaseeq(channelname, "depth")) {
       echan->chan_id = 'Z';
       ok = true;
     }
 
     if (ok == false) {
-      BLI_strncpy(tokenbuf, token, std::min(len + 1, EXR_TOT_MAXNAME));
-      printf("multilayer read: unknown channel token: %s\n", tokenbuf);
+      printf("multilayer read: unknown channel token: %s\n", channelname);
       return 0;
     }
   }



More information about the Bf-blender-cvs mailing list