mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
Syndicate, test and fix base64 implementation
llvm/Support/Base64, fix its implementation and provide a decent test suite. Previous implementation code was using + operator instead of | to combine results, which is a problem when shifting signed values. (0xFF << 16) is implicitly converted to a (signed) int, and thus results in 0xffff0000, h is negative. Combining negative numbers with a + in that context is not what we want to do. This is a recommit of 5a1958f2673f8c771e406a7e309e160b432c9a79 with UB removved. This fixes https://github.com/llvm/llvm-project/issues/149. Differential Revision: https://reviews.llvm.org/D75057
This commit is contained in:
parent
45803efcda
commit
0f08a282ef
56
include/llvm/Support/Base64.h
Normal file
56
include/llvm/Support/Base64.h
Normal file
@ -0,0 +1,56 @@
|
||||
//===--- Base64.h - Base64 Encoder/Decoder ----------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides generic base64 encoder/decoder.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_BASE64_H
|
||||
#define LLVM_SUPPORT_BASE64_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <class InputBytes> std::string encodeBase64(InputBytes const &Bytes) {
|
||||
static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
std::string Buffer;
|
||||
Buffer.resize(((Bytes.size() + 2) / 3) * 4);
|
||||
|
||||
size_t i = 0, j = 0;
|
||||
for (size_t n = Bytes.size() / 3 * 3; i < n; i += 3, j += 4) {
|
||||
uint32_t x = ((unsigned char)Bytes[i] << 16) |
|
||||
((unsigned char)Bytes[i + 1] << 8) |
|
||||
(unsigned char)Bytes[i + 2];
|
||||
Buffer[j + 0] = Table[(x >> 18) & 63];
|
||||
Buffer[j + 1] = Table[(x >> 12) & 63];
|
||||
Buffer[j + 2] = Table[(x >> 6) & 63];
|
||||
Buffer[j + 3] = Table[x & 63];
|
||||
}
|
||||
if (i + 1 == Bytes.size()) {
|
||||
uint32_t x = ((unsigned char)Bytes[i] << 16);
|
||||
Buffer[j + 0] = Table[(x >> 18) & 63];
|
||||
Buffer[j + 1] = Table[(x >> 12) & 63];
|
||||
Buffer[j + 2] = '=';
|
||||
Buffer[j + 3] = '=';
|
||||
} else if (i + 2 == Bytes.size()) {
|
||||
uint32_t x =
|
||||
((unsigned char)Bytes[i] << 16) | ((unsigned char)Bytes[i + 1] << 8);
|
||||
Buffer[j + 0] = Table[(x >> 18) & 63];
|
||||
Buffer[j + 1] = Table[(x >> 12) & 63];
|
||||
Buffer[j + 2] = Table[(x >> 6) & 63];
|
||||
Buffer[j + 3] = '=';
|
||||
}
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
52
unittests/Support/Base64Test.cpp
Normal file
52
unittests/Support/Base64Test.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
//===- llvm/unittest/Support/Base64Test.cpp - Base64 tests
|
||||
//--------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements unit tests for the Base64 functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/Base64.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
/// Tests an arbitrary set of bytes passed as \p Input.
|
||||
void TestBase64(StringRef Input, StringRef Final) {
|
||||
auto Res = encodeBase64(Input);
|
||||
EXPECT_EQ(Res, Final);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(Base64Test, Base64) {
|
||||
// from: https://tools.ietf.org/html/rfc4648#section-10
|
||||
TestBase64("", "");
|
||||
TestBase64("f", "Zg==");
|
||||
TestBase64("fo", "Zm8=");
|
||||
TestBase64("foo", "Zm9v");
|
||||
TestBase64("foob", "Zm9vYg==");
|
||||
TestBase64("fooba", "Zm9vYmE=");
|
||||
TestBase64("foobar", "Zm9vYmFy");
|
||||
|
||||
// With non-printable values.
|
||||
char NonPrintableVector[] = {0x00, 0x00, 0x00, 0x46,
|
||||
0x00, 0x08, (char)0xff, (char)0xee};
|
||||
TestBase64({NonPrintableVector, sizeof(NonPrintableVector)}, "AAAARgAI/+4=");
|
||||
|
||||
// Large test case
|
||||
char LargeVector[] = {0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b,
|
||||
0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6f,
|
||||
0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x73, 0x20, 0x6f,
|
||||
0x76, 0x65, 0x72, 0x20, 0x31, 0x33, 0x20, 0x6c, 0x61,
|
||||
0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67, 0x73, 0x2e};
|
||||
TestBase64({LargeVector, sizeof(LargeVector)},
|
||||
"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIDEzIGxhenkgZG9ncy4=");
|
||||
}
|
@ -9,6 +9,7 @@ add_llvm_unittest(SupportTests
|
||||
AnnotationsTest.cpp
|
||||
ARMAttributeParser.cpp
|
||||
ArrayRecyclerTest.cpp
|
||||
Base64Test.cpp
|
||||
BinaryStreamTest.cpp
|
||||
BlockFrequencyTest.cpp
|
||||
BranchProbabilityTest.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user