fix base64 crash
This commit is contained in:
parent
e96e8d9ad7
commit
406b598dbb
@ -16,10 +16,13 @@ namespace sled {
|
|||||||
|
|
||||||
class Base64 {
|
class Base64 {
|
||||||
public:
|
public:
|
||||||
static std::string Encode(void *ptr, size_t len);
|
static std::string Encode(const uint8_t *const ptr, size_t len);
|
||||||
static std::string Encode(const std::vector<unsigned char> &data);
|
static std::string Encode(const std::vector<unsigned char> &data);
|
||||||
static std::string Encode(const std::string &data);
|
static std::string Encode(const std::string &data);
|
||||||
|
static std::string Encode(const char *const data);
|
||||||
static StatusOr<std::string> Decode(const std::string &base64);
|
static StatusOr<std::string> Decode(const std::string &base64);
|
||||||
|
static StatusOr<std::string> Decode(const std::vector<unsigned char> &base64);
|
||||||
|
static StatusOr<std::string> Decode(const uint8_t *const ptr, size_t len);
|
||||||
};
|
};
|
||||||
|
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
#include "sled/strings/base64.h"
|
#include "sled/strings/base64.h"
|
||||||
|
#include "sled/log/log.h"
|
||||||
#include "sled/synchronization/call_once.h"
|
#include "sled/synchronization/call_once.h"
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
const char kBase64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
const char kBase64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
static int kInvBase64Chars[(1 << sizeof(char))];
|
std::array<int, 1 << (8 * sizeof(char))> kInvBase64Chars;
|
||||||
|
// static int kInvBase64Chars[(1 << sizeof(char))];
|
||||||
static OnceFlag once_flag;
|
static OnceFlag once_flag;
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@ -15,16 +17,22 @@ IsBase64(char c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
Base64::Encode(void *ptr, size_t len)
|
Base64::Encode(const uint8_t *const ptr, size_t len)
|
||||||
{
|
{
|
||||||
auto data = reinterpret_cast<unsigned char *>(ptr);
|
auto data = (unsigned char *) (ptr);
|
||||||
return Encode(std::vector<unsigned char>(data, data + len));
|
return Encode(std::vector<unsigned char>(data, data + len));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
Base64::Encode(const std::string &input)
|
Base64::Encode(const std::string &input)
|
||||||
{
|
{
|
||||||
return Encode((void *) input.data(), input.length());
|
return Encode((uint8_t *) input.data(), input.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Base64::Encode(const char *const data)
|
||||||
|
{
|
||||||
|
return Encode((uint8_t *) data, strlen(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
@ -57,8 +65,8 @@ StatusOr<std::string>
|
|||||||
Base64::Decode(const std::string &input)
|
Base64::Decode(const std::string &input)
|
||||||
{
|
{
|
||||||
CallOnce(once_flag, [&] {
|
CallOnce(once_flag, [&] {
|
||||||
std::fill(kInvBase64Chars, kInvBase64Chars + sizeof(kInvBase64Chars), -1);
|
std::fill(kInvBase64Chars.begin(), kInvBase64Chars.end(), -1);
|
||||||
for (int i = 0; i < sizeof(kBase64Chars); i++) { kInvBase64Chars[kBase64Chars[i]] = i; }
|
for (int i = 0; kBase64Chars[i]; i++) { kInvBase64Chars[kBase64Chars[i]] = i; }
|
||||||
});
|
});
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
@ -87,4 +95,16 @@ Base64::Decode(const std::string &input)
|
|||||||
|
|
||||||
return make_status_or<std::string>(ss.str());
|
return make_status_or<std::string>(ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusOr<std::string>
|
||||||
|
Base64::Decode(const std::vector<unsigned char> &base64)
|
||||||
|
{
|
||||||
|
return Decode(std::string(base64.begin(), base64.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusOr<std::string>
|
||||||
|
Base64::Decode(const uint8_t *const ptr, size_t len)
|
||||||
|
{
|
||||||
|
return Decode(std::string((char *) ptr, len));
|
||||||
|
}
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
@ -6,13 +6,36 @@
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||||
{
|
{
|
||||||
std::string encoded = sled::Base64::Encode((void *) data, size);
|
if (size < 1) { return 0; }
|
||||||
|
|
||||||
auto decoded_or = sled::Base64::Decode(encoded);
|
std::string encoded;
|
||||||
|
sled::StatusOr<std::string> decoded_or;
|
||||||
|
switch ((*data & 2)) {
|
||||||
|
case 0:
|
||||||
|
encoded = sled::Base64::Encode(data + 1, size - 1);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
encoded = sled::Base64::Encode(std::vector<uint8_t>(data + 1, data + size));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
encoded = sled::Base64::Encode(std::string((char *) data + 1, size - 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch ((*data >> 2) & 2) {
|
||||||
|
case 0:
|
||||||
|
decoded_or = sled::Base64::Decode(encoded);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
decoded_or = sled::Base64::Decode((uint8_t *) encoded.data(), encoded.size());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
decoded_or = sled::Base64::Decode(std::vector<uint8_t>(encoded.begin(), encoded.end()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(decoded_or.ok(), "decoded failed");
|
ASSERT(decoded_or.ok(), "decoded failed");
|
||||||
auto decoded = decoded_or.value();
|
auto decoded = decoded_or.value();
|
||||||
ASSERT(decoded.size() == size, "decoded size mismatch");
|
ASSERT(decoded.size() == size - 1, "decoded size mismatch");
|
||||||
ASSERT(memcmp(decoded.data(), data, size) == 0, "decoded data mismatch");
|
ASSERT(memcmp(decoded.data(), data + 1, size - 1) == 0, "decoded data mismatch");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,24 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <sled/strings/base64.h>
|
#include <sled/strings/base64.h>
|
||||||
|
|
||||||
#define CONCAT_IMPL(A, B) A##B
|
|
||||||
#define CONCAT(A, B) CONCAT_IMPL(A, B)
|
|
||||||
|
|
||||||
#define TEST_ENCODE_DECODE(base64, text) \
|
#define TEST_ENCODE_DECODE(base64, text) \
|
||||||
do { \
|
do { \
|
||||||
ASSERT_EQ(sled::Base64::Encode(text), base64); \
|
EXPECT_EQ(sled::Base64::Encode(text), std::string(base64)); \
|
||||||
auto CONCAT(res, __LINE__) = sled::Base64::Decode(base64); \
|
auto res = sled::Base64::Decode(base64); \
|
||||||
ASSERT_TRUE(CONCAT(res, __LINE__).ok()); \
|
EXPECT_TRUE(res.ok()); \
|
||||||
ASSERT_EQ(CONCAT(res, __LINE__).value(), text); \
|
EXPECT_EQ(res.value(), text); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
TEST(Base64, Encode) { EXPECT_EQ("aGVsbG8gd29ybGQK", sled::Base64::Encode("hello world\n")); }
|
||||||
|
|
||||||
|
TEST(Base64, Decode) { EXPECT_EQ("hello world\n", sled::Base64::Decode("aGVsbG8gd29ybGQK").value()); }
|
||||||
|
|
||||||
TEST(Base64, EncodeAndDecode)
|
TEST(Base64, EncodeAndDecode)
|
||||||
{
|
{
|
||||||
TEST_ENCODE_DECODE("aGVsbG8gd29ybGQK", "hello world\n");
|
TEST_ENCODE_DECODE("aGVsbG8gd29ybGQK", "hello world\n");
|
||||||
TEST_ENCODE_DECODE("", "");
|
|
||||||
TEST_ENCODE_DECODE("U2VuZCByZWluZm9yY2VtZW50cwo=", "Send reinforcements\n");
|
TEST_ENCODE_DECODE("U2VuZCByZWluZm9yY2VtZW50cwo=", "Send reinforcements\n");
|
||||||
TEST_ENCODE_DECODE(" ", " ");
|
TEST_ENCODE_DECODE("", "");
|
||||||
|
TEST_ENCODE_DECODE("IA==", " ");
|
||||||
TEST_ENCODE_DECODE("AA==", std::string("\0", 1));
|
TEST_ENCODE_DECODE("AA==", std::string("\0", 1));
|
||||||
TEST_ENCODE_DECODE("AAA=", std::string("\0\0", 2));
|
TEST_ENCODE_DECODE("AAA=", std::string("\0\0", 2));
|
||||||
TEST_ENCODE_DECODE("AAAA", std::string("\0\0\0", 3));
|
TEST_ENCODE_DECODE("AAAA", std::string("\0\0\0", 3));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user