From 047132a3a7d64be2e947fa5329c96e0243024119 Mon Sep 17 00:00:00 2001 From: wangt1xiuyi <13547954130@163.com> Date: Fri, 20 Aug 2021 10:45:52 +0800 Subject: [PATCH] fix some potential bugs --- .../engine/expr/ob_expr_regexp_context.cpp | 71 +++++++++++-------- src/sql/parser/ob_parser.cpp | 21 +++--- src/sql/parser/ob_parser.h | 12 +++- 3 files changed, 66 insertions(+), 38 deletions(-) diff --git a/src/sql/engine/expr/ob_expr_regexp_context.cpp b/src/sql/engine/expr/ob_expr_regexp_context.cpp index 7c423e190..23d7784d2 100644 --- a/src/sql/engine/expr/ob_expr_regexp_context.cpp +++ b/src/sql/engine/expr/ob_expr_regexp_context.cpp @@ -689,11 +689,16 @@ int ObExprRegexContext::replace(const ObString& text, const ObString& to, ObSEAr if (OB_UNLIKELY(real_tot_length > tot_length)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get invalid argument", K(real_tot_length), K(tot_length), K(ret)); - } else { - char* real_buf = static_cast(string_buf.alloc(real_tot_length)); - MEMSET(real_buf, 0, real_tot_length); - MEMCPY(real_buf, buf, real_tot_length); - sub.assign_ptr(real_buf, static_cast(real_tot_length)); + } else if (real_tot_length > 0) { + char *real_buf = static_cast(string_buf.alloc(real_tot_length)); + if (OB_ISNULL(real_buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("alloc memory failed.", K(real_buf), K(ret)); + } else { + MEMSET(real_buf, 0, real_tot_length); + MEMCPY(real_buf, buf, real_tot_length); + sub.assign_ptr(real_buf, static_cast(real_tot_length)); + } } } } @@ -760,27 +765,32 @@ int ObExprRegexContext::w2c( if (length < 0 || (length > 0 && OB_ISNULL(wc))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("source text is null or length is vaild", K(ret), K(wc), K(length)); - } else { + } else if (length > 0) { int32_t buff_len = sizeof(wchar_t); - char* buff = static_cast(string_buf.alloc(buff_len)); int64_t chr_len = (length + 1) * buff_len; - chr = static_cast(string_buf.alloc(chr_len)); - char* tmp_chr = chr; - MEMSET(chr, 0, chr_len); - MEMSET(buff, 0, buff_len); - for (int64_t i = 0; OB_SUCC(ret) && i < length; ++i) { - int32_t wc_int = static_cast(wc[i]); - int32_t real_length = 0; - if (OB_FAIL(ObCharset::wc_mb( - ObCharset::get_default_collation_oracle(CHARSET_UTF8MB4), wc_int, buff, buff_len, real_length))) { - LOG_WARN("failed to multi byte to wide char", K(ret)); - } else if (OB_UNLIKELY(chr_length + real_length > chr_len)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected error", K(chr_length), K(real_length), K(chr_len), K(ret)); - } else { - MEMCPY(tmp_chr, buff, real_length); - chr_length += real_length; - tmp_chr = tmp_chr + real_length; + char *buff = NULL; + if (OB_ISNULL(buff = static_cast(string_buf.alloc(buff_len))) || + OB_ISNULL(chr = static_cast(string_buf.alloc(chr_len)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("alloc memory failed.", K(buff), K(chr), K(ret)); + } else { + char *tmp_chr = chr; + MEMSET(chr, 0, chr_len); + MEMSET(buff, 0, buff_len); + for (int64_t i = 0; OB_SUCC(ret) && i < length; ++i) { + int32_t wc_int = static_cast(wc[i]); + int32_t real_length = 0; + if (OB_FAIL(ObCharset::wc_mb( + ObCharset::get_default_collation_oracle(CHARSET_UTF8MB4), wc_int, buff, buff_len, real_length))) { + LOG_WARN("failed to multi byte to wide char", K(ret)); + } else if (OB_UNLIKELY(chr_length + real_length > chr_len)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(chr_length), K(real_length), K(chr_len), K(ret)); + } else { + MEMCPY(tmp_chr, buff, real_length); + chr_length += real_length; + tmp_chr = tmp_chr + real_length; + } } } } @@ -926,10 +936,15 @@ int ObExprRegexContext::pre_process_replace_str(const ObString& text, const ObSt MEMCPY(tmp_buf, to_ptr + length_to - 1, 1); ++real_tot_length; } - char* real_buf = static_cast(string_buf.alloc(real_tot_length)); - MEMSET(real_buf, 0, real_tot_length); - MEMCPY(real_buf, buf, real_tot_length); - tmp_string.assign_ptr(real_buf, static_cast(real_tot_length)); + char *real_buf = static_cast(string_buf.alloc(real_tot_length)); + if (OB_ISNULL(real_buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("alloc memory failed.", K(real_buf), K(ret)); + } else { + MEMSET(real_buf, 0, real_tot_length); + MEMCPY(real_buf, buf, real_tot_length); + tmp_string.assign_ptr(real_buf, static_cast(real_tot_length)); + } } if (OB_SUCC(ret) && OB_FAIL(to_strings.push_back(tmp_string))) { LOG_WARN("failed to push back string", K(ret)); diff --git a/src/sql/parser/ob_parser.cpp b/src/sql/parser/ob_parser.cpp index 54065002b..106b8960e 100644 --- a/src/sql/parser/ob_parser.cpp +++ b/src/sql/parser/ob_parser.cpp @@ -107,7 +107,7 @@ int ObParser::split_multiple_stmt( ObString part(str_len, stmt.ptr() + offset); ObString remain_part(remain, stmt.ptr() + offset); //first try parse part str, because it's have less length and need less memory - if (OB_FAIL(tmp_ret = parse(part, parse_result, parse_mode))) { + if (OB_FAIL(tmp_ret = parse(part, parse_result, parse_mode, false, true))) { //if parser part str failed, then try parse all remain part, avoid parse many times: //bug: https://work.aone.alibaba-inc.com/issue/34642901 tmp_ret = OB_SUCCESS; @@ -146,12 +146,14 @@ int ObParser::split_multiple_stmt( return ret; } -int ObParser::parse_sql(const ObString& stmt, ParseResult& parse_result) +int ObParser::parse_sql(const ObString& stmt, ParseResult& parse_result, const bool no_throw_parser_error) { int ret = OB_SUCCESS; ObSQLParser sql_parser(*(ObIAllocator*)(parse_result.malloc_pool_), sql_mode_); if (OB_FAIL(sql_parser.parse(stmt.ptr(), stmt.length(), parse_result))) { - LOG_INFO("failed to parse stmt as sql", K(stmt), K(ret)); + if (!no_throw_parser_error) { + LOG_INFO("failed to parse stmt as sql", K(stmt), K(ret)); + } } else if (parse_result.is_dynamic_sql_) { memmove(parse_result.no_param_sql_ + parse_result.no_param_sql_len_, parse_result.input_sql_ + parse_result.pl_parse_info_.last_pl_symbol_pos_, @@ -160,11 +162,11 @@ int ObParser::parse_sql(const ObString& stmt, ParseResult& parse_result) } else { /*do nothing*/ } if (parse_result.is_fp_ || parse_result.is_multi_query_) { - if (OB_FAIL(ret)) { + if (OB_FAIL(ret) && !no_throw_parser_error) { LOG_WARN("failed to fast parameterize", K(stmt), K(ret)); } } - if (OB_FAIL(ret)) { + if (OB_FAIL(ret) && !no_throw_parser_error) { auto err_charge_sql_mode = lib::is_oracle_mode(); LOG_WARN("failed to parse the statement", K(stmt), @@ -206,7 +208,8 @@ int ObParser::parse_sql(const ObString& stmt, ParseResult& parse_result) } int ObParser::parse( - const ObString& query, ParseResult& parse_result, ParseMode parse_mode, const bool is_batched_multi_stmt_split_on) + const ObString& query, ParseResult& parse_result, ParseMode parse_mode, const bool is_batched_multi_stmt_split_on, + const bool no_throw_parser_error) { int ret = OB_SUCCESS; @@ -268,8 +271,10 @@ int ObParser::parse( LOG_DEBUG("check parse_result param", "connection charset", ObCharset::charset_name(connection_collation_)); } if (OB_SUCC(ret)) { - if (OB_FAIL(parse_sql(stmt, parse_result))) { - LOG_WARN("failed to parse stmt as sql", K(stmt), K(parse_mode), K(ret)); + if (OB_FAIL(parse_sql(stmt, parse_result, no_throw_parser_error))) { + if (!no_throw_parser_error) { + LOG_WARN("failed to parse stmt as sql", K(stmt), K(parse_mode), K(ret)); + } } } return ret; diff --git a/src/sql/parser/ob_parser.h b/src/sql/parser/ob_parser.h index 8c993d875..4e920c4f7 100644 --- a/src/sql/parser/ob_parser.h +++ b/src/sql/parser/ob_parser.h @@ -53,10 +53,18 @@ public: bool is_single_stmt(const common::ObString& stmt); int split_multiple_stmt(const common::ObString& stmt, common::ObIArray& queries, ObMPParseStat& parse_fail, bool is_ret_first_stmt = false); - int parse_sql(const common::ObString& stmt, ParseResult& parse_result); + //@param: + // no_throw_parser_error is used to mark not throw parser error. in the split multi stmt + // situation we will try find ';' delimiter to parser part of string in case of save memory, + // but this maybe parser error and throw error info. However, we will still try parser remain + // string when parse part of string failed, if we throw parse part error info, maybe will let + // someone misunderstand have bug, So, we introduce this mark to decide to throw parser erorr. + // eg: select '123;' from dual; select '123' from dual; + int parse_sql(const common::ObString& stmt, ParseResult& parse_result, + const bool no_throw_parser_error = false); virtual int parse(const common::ObString& stmt, ParseResult& parse_result, ParseMode mode = STD_MODE, - const bool is_batched_multi_stmt_split_on = false); + const bool is_batched_multi_stmt_split_on = false, const bool no_throw_parser_error = false); virtual void free_result(ParseResult& parse_result); /**