1*810390e3Srobert //===-- sanitizer_leb128.cpp ------------------------------------*- C++ -*-===//
2*810390e3Srobert //
3*810390e3Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*810390e3Srobert // See https://llvm.org/LICENSE.txt for license information.
5*810390e3Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*810390e3Srobert //
7*810390e3Srobert //===----------------------------------------------------------------------===//
8*810390e3Srobert #include "sanitizer_common/sanitizer_leb128.h"
9*810390e3Srobert
10*810390e3Srobert #include <type_traits>
11*810390e3Srobert
12*810390e3Srobert #include "gtest/gtest.h"
13*810390e3Srobert #include "sanitizer_common/sanitizer_common.h"
14*810390e3Srobert #include "sanitizer_internal_defs.h"
15*810390e3Srobert
16*810390e3Srobert namespace __sanitizer {
17*810390e3Srobert
18*810390e3Srobert template <typename T>
19*810390e3Srobert class Leb128Test : public ::testing::Test {};
20*810390e3Srobert
21*810390e3Srobert using Leb128TestTypes = ::testing::Types<u8, u16, u32, u64>;
22*810390e3Srobert TYPED_TEST_SUITE(Leb128Test, Leb128TestTypes, );
23*810390e3Srobert
BitsNeeded(u64 v)24*810390e3Srobert static uptr BitsNeeded(u64 v) {
25*810390e3Srobert if (!v)
26*810390e3Srobert return 1;
27*810390e3Srobert uptr r = 0;
28*810390e3Srobert if (sizeof(uptr) != sizeof(u64)) {
29*810390e3Srobert uptr uptr_bits = 8 * sizeof(uptr);
30*810390e3Srobert while (v >> uptr_bits) {
31*810390e3Srobert r += uptr_bits;
32*810390e3Srobert v >>= uptr_bits;
33*810390e3Srobert }
34*810390e3Srobert }
35*810390e3Srobert return r + MostSignificantSetBitIndex(v) + 1;
36*810390e3Srobert }
37*810390e3Srobert
TYPED_TEST(Leb128Test,SignedOverflow)38*810390e3Srobert TYPED_TEST(Leb128Test, SignedOverflow) {
39*810390e3Srobert using T = typename std::make_signed<TypeParam>::type;
40*810390e3Srobert u8 buffer[16] = {255};
41*810390e3Srobert T v = -128;
42*810390e3Srobert EXPECT_EQ(buffer + 1, EncodeSLEB128(v, buffer, buffer + 1));
43*810390e3Srobert EXPECT_EQ(buffer + 1, DecodeSLEB128(buffer, buffer + 1, &v));
44*810390e3Srobert }
45*810390e3Srobert
TYPED_TEST(Leb128Test,Signed)46*810390e3Srobert TYPED_TEST(Leb128Test, Signed) {
47*810390e3Srobert using T = typename std::make_signed<TypeParam>::type;
48*810390e3Srobert T v = 0;
49*810390e3Srobert for (int i = 0; i < 100; ++i) {
50*810390e3Srobert u8 buffer[16] = {};
51*810390e3Srobert u8* p = EncodeSLEB128(v, std::begin(buffer), std::end(buffer));
52*810390e3Srobert EXPECT_EQ(int(BitsNeeded(v < 0 ? (-v - 1) : v) + 6 + 1) / 7, p - buffer)
53*810390e3Srobert << (int)v;
54*810390e3Srobert T v2;
55*810390e3Srobert u8* p2 = DecodeSLEB128(std::begin(buffer), std::end(buffer), &v2);
56*810390e3Srobert EXPECT_EQ(v, v2);
57*810390e3Srobert EXPECT_EQ(p, p2);
58*810390e3Srobert v = -TypeParam(v) * 3u + 1u;
59*810390e3Srobert }
60*810390e3Srobert }
61*810390e3Srobert
TYPED_TEST(Leb128Test,UnsignedOverflow)62*810390e3Srobert TYPED_TEST(Leb128Test, UnsignedOverflow) {
63*810390e3Srobert using T = TypeParam;
64*810390e3Srobert u8 buffer[16] = {255};
65*810390e3Srobert T v = 255;
66*810390e3Srobert EXPECT_EQ(buffer + 1, EncodeULEB128(v, buffer, buffer + 1));
67*810390e3Srobert EXPECT_EQ(buffer + 1, DecodeULEB128(buffer, buffer + 1, &v));
68*810390e3Srobert }
69*810390e3Srobert
TYPED_TEST(Leb128Test,Unsigned)70*810390e3Srobert TYPED_TEST(Leb128Test, Unsigned) {
71*810390e3Srobert using T = TypeParam;
72*810390e3Srobert T v = 0;
73*810390e3Srobert for (int i = 0; i < 100; ++i) {
74*810390e3Srobert u8 buffer[16] = {};
75*810390e3Srobert u8* p = EncodeULEB128(v, std::begin(buffer), std::end(buffer));
76*810390e3Srobert EXPECT_EQ(int(BitsNeeded(v) + 6) / 7, p - buffer);
77*810390e3Srobert T v2;
78*810390e3Srobert u8* p2 = DecodeULEB128(std::begin(buffer), std::end(buffer), &v2);
79*810390e3Srobert EXPECT_EQ(v, v2);
80*810390e3Srobert EXPECT_EQ(p, p2);
81*810390e3Srobert v = v * 3 + 1;
82*810390e3Srobert }
83*810390e3Srobert }
84*810390e3Srobert
85*810390e3Srobert } // namespace __sanitizer
86