Fix From_base64 bugs
This commit is contained in:
57
deps/oblib/src/lib/encode/ob_base64_encode.cpp
vendored
57
deps/oblib/src/lib/encode/ob_base64_encode.cpp
vendored
@ -158,8 +158,24 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len,
|
||||
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",
|
||||
input, output, input_len, output_len, pos);
|
||||
@ -177,10 +193,8 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len,
|
||||
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",
|
||||
@ -204,27 +218,28 @@ int ObBase64Encoder::decode(const char *input, const int64_t input_len,
|
||||
}
|
||||
} // 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]];
|
||||
|
||||
17
deps/oblib/src/lib/encode/ob_base64_encode.h
vendored
17
deps/oblib/src/lib/encode/ob_base64_encode.h
vendored
@ -35,14 +35,6 @@ static int FROM_BASE64_TABLE[];
|
||||
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:
|
||||
static constexpr int64_t needed_encoded_length(const int64_t buf_size)
|
||||
@ -55,6 +47,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);
|
||||
|
||||
@ -27,7 +27,7 @@ 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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -126,21 +126,18 @@ int ObExprFromBase64::eval_from_base64(const ObExpr &expr,
|
||||
} 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;
|
||||
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
|
||||
output_buf = static_cast<char*>(alloc_guard.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();
|
||||
@ -181,20 +178,17 @@ int ObExprFromBase64::eval_from_base64_batch(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
ObDatum *arg = args.at(j);
|
||||
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[j].set_string(nullptr, 0);
|
||||
} else {
|
||||
const char *buf = in_raw.ptr();
|
||||
char *output_buf = nullptr;
|
||||
int64_t buf_len = base64_needed_decoded_length(in_raw_len);
|
||||
int64_t pos = 0;
|
||||
output_buf = static_cast<char*>(alloc_guard.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[j].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[j].set_null();
|
||||
|
||||
@ -20,7 +20,7 @@ namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprFromBase64 : public ObFuncExprOperator {
|
||||
class ObExprFromBase64 : public ObStringExprOperator {
|
||||
public:
|
||||
explicit ObExprFromBase64(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprFromBase64();
|
||||
|
||||
@ -27,7 +27,7 @@ namespace sql
|
||||
{
|
||||
|
||||
ObExprToBase64::ObExprToBase64(ObIAllocator &alloc)
|
||||
:ObFuncExprOperator(alloc, T_FUN_SYS_TO_BASE64, N_TO_BASE64, 1, NOT_ROW_DIMENSION)
|
||||
:ObStringExprOperator(alloc, T_FUN_SYS_TO_BASE64, N_TO_BASE64, 1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprToBase64 : public ObFuncExprOperator
|
||||
class ObExprToBase64 : public ObStringExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprToBase64(common::ObIAllocator &alloc);
|
||||
|
||||
Reference in New Issue
Block a user