提交 bfb1de90 编写于 作者: O obdev 提交者: ob-robot

[CP] Fix From_base64 bugs

上级 a501ceac
......@@ -382,7 +382,29 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len, uint8_t
int64_t &pos, bool skip_spaces)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(input) || OB_ISNULL(output) || OB_UNLIKELY(input_len < 0 || output_len < 0 || pos < 0)) {
bool all_skipped = false;
if (OB_ISNULL(input) || OB_UNLIKELY(input_len < 0 || output_len < 0 || pos < 0)) {
ret = OB_INVALID_ARGUMENT;
_OB_LOG(WARN,
"invalid argument input=%p, output=%p, input_len=%ld, output_len=%ld, pos=%ld",
input,
output,
input_len,
output_len,
pos);
} else if (skip_spaces) {
all_skipped = true;
for (int64_t i = 0; all_skipped && i < input_len; ++i) {
if (!ObBase64Encoder::my_base64_decoder_skip_spaces(input[i])) {
all_skipped = false;
}
}
}
if (OB_FAIL(ret)) {
} else if (all_skipped) {
// return empty string
pos = 0;
} else if (OB_ISNULL(output)) {
ret = OB_INVALID_ARGUMENT;
_OB_LOG(WARN,
"invalid argument input=%p, output=%p, input_len=%ld, output_len=%ld, pos=%ld",
......@@ -405,10 +427,8 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len, uint8_t
int64_t skipped_spaces = 0;
for(; OB_SUCC(ret) && iter_input < (input + input_len) && '=' != *iter_input; iter_input++) {
if (OB_UNLIKELY(!is_base64_char(*iter_input))) {
if (skip_spaces) {
if (my_base64_decoder_skip_spaces(*iter_input)) {
++skipped_spaces;
}
if (skip_spaces && my_base64_decoder_skip_spaces(*iter_input)) {
++skipped_spaces;
} else {
ret = OB_INVALID_ARGUMENT;
_OB_LOG(WARN, "invalid base64 char, cur_idx=%ld, char=%c", iter_input - input, *iter_input);
......@@ -431,27 +451,28 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len, uint8_t
}
} // for end
int64_t cur_idx = iter_input - input;
for (const char *iter = iter_input; iter < input + input_len; iter++) {
if (skip_spaces) {
if (my_base64_decoder_skip_spaces(*iter)) {
++skipped_spaces;
}
} else {
// all the rest chars must be '='
if (OB_UNLIKELY('=' != *iter)) {
ret = OB_INVALID_ARGUMENT;
}
int64_t cur_valid_len = iter_input - input - skipped_spaces;
for (const char *iter = iter_input; OB_SUCC(ret) && iter < input + input_len; iter++) {
// all the rest chars must be '='
if (skip_spaces && my_base64_decoder_skip_spaces(*iter)) {
skipped_spaces++;
} else if (OB_UNLIKELY('=' != *iter)) {
ret = OB_INVALID_ARGUMENT;
}
} // end for
if (skip_spaces) {
if (OB_FAIL(ret)) {
} else if (!skip_spaces) {
if (OB_UNLIKELY((cur_idx + 3 <= input_len))) {
// only last char or last two chars can be '='
ret = OB_INVALID_ARGUMENT;
}
} else {
int64_t valid_len = input_len - skipped_spaces;
if (valid_len % 4 != 0 || valid_len < 4 || cur_idx + 3 <= valid_len) {
if (valid_len % 4 != 0 || cur_valid_len + 3 <= valid_len) {
ret = OB_INVALID_ARGUMENT;
}
}
if (OB_UNLIKELY((cur_idx + 3 <= input_len) && !skip_spaces)) {
// only last char or last two chars can be '='
ret = OB_INVALID_ARGUMENT;
if (OB_FAIL(ret)) {
} else if (i > 0) {
for (int k = 0; k < i; k++) {
uint8_array_4[k] = BASE64_VALUES[uint8_array_4[k]];
......
......@@ -32,14 +32,6 @@ private:
return std::isalnum(c) || c == '+' || c == '/';
}
static inline bool my_base64_decoder_skip_spaces(char c)
{
if (FROM_BASE64_TABLE[(uint8_t)c] != -2) {
return false;
}
return true;
}
static const int64_t SOFT_NEW_LINE_STR_POS = 19;
public:
......@@ -53,6 +45,15 @@ public:
return (buf_size / 4) * 3;
}
static inline bool my_base64_decoder_skip_spaces(char c)
{
if (FROM_BASE64_TABLE[(uint8_t)c] != -2) {
return false;
}
return true;
}
static int encode(const uint8_t *input, const int64_t input_len, char *output, const int64_t output_len, int64_t &pos,
const int16_t wrap = 0);
......
......@@ -24,7 +24,7 @@ namespace oceanbase {
namespace sql {
ObExprFromBase64::ObExprFromBase64(ObIAllocator &alloc)
: ObFuncExprOperator(alloc, T_FUN_SYS_FROM_BASE64, N_FROM_BASE64, 1, NOT_ROW_DIMENSION)
: ObStringExprOperator(alloc, T_FUN_SYS_FROM_BASE64, N_FROM_BASE64, 1)
{}
ObExprFromBase64::~ObExprFromBase64()
......@@ -47,11 +47,7 @@ int ObExprFromBase64::calc(ObObj &result, const ObObj &obj, ObIAllocator *alloca
int64_t buf_len = base64_needed_decoded_length(in_raw_len);
int64_t pos = 0;
char *output_buf = static_cast<char *>(allocator->alloc(buf_len));
if (OB_ISNULL(output_buf)) {
LOG_WARN("output_buf is null", K(ret), K(buf_len), K(in_raw_len));
result.set_null();
} else if (OB_FAIL(ObBase64Encoder::decode(
buf, in_raw_len, reinterpret_cast<uint8_t *>(output_buf), buf_len, pos, true))) {
if (OB_FAIL(ObBase64Encoder::decode(buf, in_raw_len, reinterpret_cast<uint8_t *>(output_buf), buf_len, pos, true))) {
if (OB_UNLIKELY(ret == OB_INVALID_ARGUMENT)) {
ret = OB_SUCCESS;
result.set_null();
......@@ -131,19 +127,15 @@ int ObExprFromBase64::eval_from_base64(const ObExpr &expr, ObEvalCtx &ctx, ObDat
} else {
const ObString &in_raw = arg->get_string();
ObLength in_raw_len = in_raw.length();
if (OB_UNLIKELY(in_raw_len == 0)) {
const char *buf = in_raw.ptr();
if (NULL == buf) {
res.set_string(nullptr, 0);
} else {
const char *buf = in_raw.ptr();
char *output_buf = nullptr;
char *output_buf = NULL;
int64_t buf_len = base64_needed_decoded_length(in_raw_len);
int64_t pos = 0;
output_buf = static_cast<char *>(exec_ctx->get_allocator().alloc(buf_len));
if (OB_ISNULL(output_buf)) {
LOG_WARN("output_buf is null", K(ret), K(buf_len), K(in_raw_len));
res.set_null();
} else if (OB_FAIL(ObBase64Encoder::decode(
buf, in_raw_len, reinterpret_cast<uint8_t *>(output_buf), buf_len, pos, true))) {
if (OB_FAIL(ObBase64Encoder::decode(buf, in_raw_len, reinterpret_cast<uint8_t *>(output_buf), buf_len, pos, true))) {
if (OB_UNLIKELY(ret == OB_INVALID_ARGUMENT)) {
ret = OB_SUCCESS;
res.set_null();
......
......@@ -18,7 +18,7 @@
namespace oceanbase {
namespace sql {
class ObExprFromBase64 : public ObFuncExprOperator {
class ObExprFromBase64 : public ObStringExprOperator {
public:
explicit ObExprFromBase64(common::ObIAllocator &alloc);
virtual ~ObExprFromBase64();
......
......@@ -23,8 +23,7 @@ using namespace oceanbase::common;
namespace oceanbase {
namespace sql {
ObExprToBase64::ObExprToBase64(ObIAllocator &alloc)
: ObFuncExprOperator(alloc, T_FUN_SYS_TO_BASE64, N_TO_BASE64, 1, NOT_ROW_DIMENSION)
ObExprToBase64::ObExprToBase64(ObIAllocator &alloc) : ObStringExprOperator(alloc, T_FUN_SYS_TO_BASE64, N_TO_BASE64, 1)
{}
ObExprToBase64::~ObExprToBase64()
......
......@@ -18,7 +18,7 @@
namespace oceanbase {
namespace sql {
class ObExprToBase64 : public ObFuncExprOperator {
class ObExprToBase64 : public ObStringExprOperator {
public:
explicit ObExprToBase64(common::ObIAllocator &alloc);
virtual ~ObExprToBase64();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册