mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 05:27:46 +00:00
AK+Everywhere: Make Base64 decoding fallible
This commit is contained in:
parent
3bf1f7ae87
commit
cb868cfa41
11 changed files with 73 additions and 32 deletions
|
@ -6,10 +6,7 @@
|
|||
|
||||
#include <AK/Array.h>
|
||||
#include <AK/Base64.h>
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/Vector.h>
|
||||
|
||||
|
@ -33,7 +30,8 @@ static constexpr auto make_alphabet()
|
|||
static constexpr auto make_lookup_table()
|
||||
{
|
||||
constexpr auto alphabet = make_alphabet();
|
||||
Array<u8, 256> table {};
|
||||
Array<i16, 256> table;
|
||||
table.fill(-1);
|
||||
for (size_t i = 0; i < alphabet.size(); ++i) {
|
||||
table[alphabet[i]] = i;
|
||||
}
|
||||
|
@ -50,19 +48,31 @@ size_t calculate_base64_encoded_length(ReadonlyBytes input)
|
|||
return ((4 * input.size() / 3) + 3) & ~3;
|
||||
}
|
||||
|
||||
ByteBuffer decode_base64(const StringView& input)
|
||||
Optional<ByteBuffer> decode_base64(const StringView& input)
|
||||
{
|
||||
auto get = [&](const size_t offset, bool* is_padding = nullptr) -> u8 {
|
||||
auto get = [&](const size_t offset, bool* is_padding) -> Optional<u8> {
|
||||
constexpr auto table = make_lookup_table();
|
||||
if (offset >= input.length())
|
||||
return 0;
|
||||
if (input[offset] == '=') {
|
||||
if (is_padding)
|
||||
*is_padding = true;
|
||||
if (!is_padding)
|
||||
return {};
|
||||
*is_padding = true;
|
||||
return 0;
|
||||
}
|
||||
return table[static_cast<unsigned char>(input[offset])];
|
||||
i16 result = table[static_cast<unsigned char>(input[offset])];
|
||||
if (result < 0)
|
||||
return {};
|
||||
VERIFY(result < 256);
|
||||
return { result };
|
||||
};
|
||||
#define TRY_GET(index, is_padding) \
|
||||
({ \
|
||||
auto _temporary_result = get(index, is_padding); \
|
||||
if (!_temporary_result.has_value()) \
|
||||
return {}; \
|
||||
_temporary_result.value(); \
|
||||
})
|
||||
|
||||
Vector<u8> output;
|
||||
output.ensure_capacity(calculate_base64_decoded_length(input));
|
||||
|
@ -71,10 +81,10 @@ ByteBuffer decode_base64(const StringView& input)
|
|||
bool in2_is_padding = false;
|
||||
bool in3_is_padding = false;
|
||||
|
||||
const u8 in0 = get(i);
|
||||
const u8 in1 = get(i + 1);
|
||||
const u8 in2 = get(i + 2, &in2_is_padding);
|
||||
const u8 in3 = get(i + 3, &in3_is_padding);
|
||||
const u8 in0 = TRY_GET(i, nullptr);
|
||||
const u8 in1 = TRY_GET(i + 1, nullptr);
|
||||
const u8 in2 = TRY_GET(i + 2, &in2_is_padding);
|
||||
const u8 in3 = TRY_GET(i + 3, &in3_is_padding);
|
||||
|
||||
const u8 out0 = (in0 << 2) | ((in1 >> 4) & 3);
|
||||
const u8 out1 = ((in1 & 0xf) << 4) | ((in2 >> 2) & 0xf);
|
||||
|
@ -87,8 +97,7 @@ ByteBuffer decode_base64(const StringView& input)
|
|||
output.append(out2);
|
||||
}
|
||||
|
||||
// FIXME: Handle OOM failure.
|
||||
return ByteBuffer::copy(output).release_value();
|
||||
return ByteBuffer::copy(output);
|
||||
}
|
||||
|
||||
String encode_base64(ReadonlyBytes input)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue