diff --git a/src/common/utils.cpp b/src/common/utils.cpp index e0f7ac42b7..b232babb8a 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -1610,6 +1610,11 @@ bool containsErrorCode(const ISC_STATUS* v, ISC_STATUS code) return false; } +inline bool sqlSymbolChar(char c, bool first) +{ + return (isdigit(c) && !first) || isalpha(c) || c == '_' || c == '$'; +} + const char* dpbItemUpper(const char* s, FB_SIZE_T l, Firebird::string& buf) { if (l && (s[0] == '"' || s[0] == '\'')) @@ -1622,30 +1627,37 @@ const char* dpbItemUpper(const char* s, FB_SIZE_T l, Firebird::string& buf) { if (s[i] == end_quote) { - if (++i >= l || s[i] != end_quote) - break; // delimited quote, done processing + if (++i >= l) + { + if (ascii && s[0] == '\'') + buf.upper(); + + return buf.c_str(); + } + + if (s[i] != end_quote) + { + buf.assign(&s[i], l - i); + Firebird::fatal_exception::raiseFmt("Invalid text <%s> after quoted string", buf.c_str()); + } // skipped the escape quote, continue processing } - - if (s[i] & 0x80) + else if (!sqlSymbolChar(s[i], i == 1)) ascii = false; + buf += s[i]; } - if (ascii && s[0] == '\'') - buf.upper(); - - return buf.c_str(); + Firebird::fatal_exception::raiseFmt("Missing terminating quote <%c> in the end of quoted string", s[0]); } // non-quoted string - try to uppercase for (FB_SIZE_T i = 0; i < l; ++i) { - if (!(s[i] & 0x80)) - buf += toupper(s[i]); - else + if (!sqlSymbolChar(s[i], i == 0)) return NULL; // contains non-ascii data + buf += toupper(s[i]); } return buf.c_str(); diff --git a/src/jrd/scl.epp b/src/jrd/scl.epp index 361589ba99..b0bed3b8f3 100644 --- a/src/jrd/scl.epp +++ b/src/jrd/scl.epp @@ -1776,7 +1776,11 @@ void UserId::makeRoleName(Firebird::MetaString& role, const int dialect) // Invoke utility twice: first to strip quotes, next to uppercase if needed // For unquoted string nothing bad happens fb_utils::dpbItemUpper(role); - fb_utils::dpbItemUpper(role); + { + Firebird::string tmp(role); + tmp.upper(); + role = tmp; + } break; case SQL_DIALECT_V6_TRANSITION: