Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix tryBase64Decode() with invalid input #56913

Merged
merged 1 commit into from Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 4 additions & 6 deletions src/Functions/FunctionBase64Conversion.h
Expand Up @@ -76,12 +76,10 @@ struct TryBase64Decode
static size_t perform(const std::span<const UInt8> src, UInt8 * dst)
{
size_t outlen = 0;
base64_decode(reinterpret_cast<const char *>(src.data()), src.size(), reinterpret_cast<char *>(dst), &outlen, 0);
int rc = base64_decode(reinterpret_cast<const char *>(src.data()), src.size(), reinterpret_cast<char *>(dst), &outlen, 0);

// during decoding character array can be partially polluted
// if fail, revert back and clean
if (!outlen)
*dst = 0;
if (rc != 1)
outlen = 0;

return outlen;
}
Expand Down Expand Up @@ -147,7 +145,7 @@ class FunctionBase64Conversion : public IFunction
for (size_t row = 0; row < src_row_count; ++row)
{
const size_t src_length = src_offsets[row] - src_offset_prev - 1;
const auto outlen = Func::perform({src, src_length}, dst_pos);
const size_t outlen = Func::perform({src, src_length}, dst_pos);

/// Base64 library is using AVX-512 with some shuffle operations.
/// Memory sanitizer don't understand if there was uninitialized memory in SIMD register but it was not used in the result of shuffle.
Expand Down
6 changes: 3 additions & 3 deletions tests/queries/0_stateless/00732_base64_functions.reference
Expand Up @@ -21,9 +21,9 @@ fooba
foobar
1 1
1 1
fooba



Zm9v
foo
foo
TEcgT3B0aW11cw==
22 changes: 15 additions & 7 deletions tests/queries/0_stateless/00732_base64_functions.sql
Expand Up @@ -2,27 +2,35 @@

SET send_logs_level = 'fatal';

SELECT base64Encode(val) FROM (select arrayJoin(['', 'f', 'fo', 'foo', 'foob', 'fooba', 'foobar']) val);
SELECT base64Encode(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
SELECT base64Decode(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
SELECT tryBase64Decode(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
SELECT base64Encode('foo', 'excess argument'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
SELECT base64Decode('foo', 'excess argument'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
SELECT tryBase64Decode('foo', 'excess argument'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }

-- test with valid inputs

SELECT base64Encode(val) FROM (select arrayJoin(['', 'f', 'fo', 'foo', 'foob', 'fooba', 'foobar']) val);
SELECT base64Decode(val) FROM (select arrayJoin(['', 'Zg==', 'Zm8=', 'Zm9v', 'Zm9vYg==', 'Zm9vYmE=', 'Zm9vYmFy']) val);
SELECT tryBase64Decode(val) FROM (select arrayJoin(['', 'Zg==', 'Zm8=', 'Zm9v', 'Zm9vYg==', 'Zm9vYmE=', 'Zm9vYmFy']) val);

SELECT base64Decode(base64Encode('foo')) = 'foo', base64Encode(base64Decode('Zm9v')) == 'Zm9v';
SELECT tryBase64Decode(base64Encode('foo')) = 'foo', base64Encode(tryBase64Decode('Zm9v')) == 'Zm9v';

SELECT base64Encode('foo', 'excess argument'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
SELECT base64Decode('foo', 'excess argument'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
SELECT tryBase64Decode('foo', 'excess argument'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
-- test with invalid inputs

SELECT base64Decode('Zm9vYmF=Zm9v'); -- { serverError INCORRECT_DATA }
SELECT tryBase64Decode('Zm9vYmF=Zm9v');

SELECT base64Decode('foo'); -- { serverError INCORRECT_DATA }
SELECT tryBase64Decode('foo');

SELECT base64Decode('aoeo054640eu='); -- { serverError INCORRECT_DATA }
SELECT tryBase64Decode('aoeo054640eu=');

-- test FixedString arguments

select base64Encode(toFixedString('foo', 3));
select base64Decode(toFixedString('Zm9v', 4));
select tryBase64Decode(toFixedString('Zm9v', 4));

-- This query reproduces a bug in TurboBase64 library (which we no longer use)
select distinct base64Encode(materialize('LG Optimus')) from numbers(100);