diff options
author | Brecht Van Lommel <brecht@blender.org> | 2022-05-09 18:17:03 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2022-05-09 19:28:24 +0300 |
commit | 78f61bf8c13460f8065eaa8eabaa2ac5a4c66a5e (patch) | |
tree | 94673857e57239130dcaca621b61b07e4f2e296d /source | |
parent | 686abf1850545f8c953a76791bd098a5259ce0d6 (diff) |
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.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenlib/BLI_string.h | 8 | ||||
-rw-r--r-- | source/blender/blenlib/intern/string.c | 18 | ||||
-rw-r--r-- | source/blender/imbuf/intern/openexr/openexr_api.cpp | 31 |
3 files changed, 36 insertions, 21 deletions
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; } } |