Serenity Operating System
at master 173 lines 5.8 kB view raw
1/* 2 * Copyright (c) 2021, Andrew Kaster <akaster@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/LEB128.h> 8#include <AK/MemoryStream.h> 9#include <AK/NumericLimits.h> 10#include <LibTest/TestCase.h> 11 12TEST_CASE(single_byte) 13{ 14 u32 output = {}; 15 i32 output_signed = {}; 16 u8 buf[] = { 0x00 }; 17 FixedMemoryStream stream { ReadonlyBytes { buf, sizeof(buf) } }; 18 19 // less than/eq 0b0011_1111, signed == unsigned == raw byte 20 for (u8 i = 0u; i <= 0x3F; ++i) { 21 buf[0] = i; 22 23 MUST(stream.seek(0)); 24 output = MUST(stream.read_value<LEB128<u32>>()); 25 EXPECT_EQ(output, i); 26 27 MUST(stream.seek(0)); 28 output_signed = MUST(stream.read_value<LEB128<i32>>()); 29 EXPECT_EQ(output_signed, i); 30 } 31 32 // 0b0100_0000 to 0b0111_1111 unsigned == byte, signed = {{ 26'b(-1), 6'b(byte) }} 33 for (u8 i = 0x40u; i < 0x80; ++i) { 34 buf[0] = i; 35 36 MUST(stream.seek(0)); 37 output = MUST(stream.read_value<LEB128<u32>>()); 38 EXPECT_EQ(output, i); 39 40 MUST(stream.seek(0)); 41 output_signed = MUST(stream.read_value<LEB128<i32>>()); 42 EXPECT_EQ(output_signed, (i | (-1 & (~0x3F)))); 43 } 44 // MSB set, but input too short 45 for (u16 i = 0x80; i <= 0xFF; ++i) { 46 buf[0] = static_cast<u8>(i); 47 48 MUST(stream.seek(0)); 49 EXPECT(stream.read_value<LEB128<u32>>().is_error()); 50 51 MUST(stream.seek(0)); 52 EXPECT(stream.read_value<LEB128<i32>>().is_error()); 53 } 54} 55 56TEST_CASE(two_bytes) 57{ 58 u32 output = {}; 59 i32 output_signed = {}; 60 u8 buf[] = { 0x00, 0x1 }; 61 FixedMemoryStream stream { ReadonlyBytes { buf, sizeof(buf) } }; 62 63 // Only test with first byte expecting more, otherwise equivalent to single byte case 64 for (u16 i = 0x80; i <= 0xFF; ++i) { 65 buf[0] = static_cast<u8>(i); 66 67 // less than/eq 0b0011_1111: signed == unsigned == (j << 7) + (7 MSB of i) 68 for (u8 j = 0u; j <= 0x3F; ++j) { 69 buf[1] = j; 70 71 MUST(stream.seek(0)); 72 output = MUST(stream.read_value<LEB128<u32>>()); 73 EXPECT_EQ(output, (static_cast<u32>(j) << 7) + (i & 0x7F)); 74 75 MUST(stream.seek(0)); 76 output_signed = MUST(stream.read_value<LEB128<i32>>()); 77 EXPECT_EQ(output_signed, (static_cast<i32>(j) << 7) + (i & 0x7F)); 78 } 79 80 // 0b0100_0000 to 0b0111_1111: unsigned == (j << 7) + (7 MSB of i), signed == {{ 19'b(-1), 6'b(j), 7'b(i) }} 81 for (u8 j = 0x40u; j < 0x80; ++j) { 82 buf[1] = j; 83 84 MUST(stream.seek(0)); 85 output = MUST(stream.read_value<LEB128<u32>>()); 86 EXPECT_EQ(output, (static_cast<u32>(j) << 7) + (i & 0x7F)); 87 88 MUST(stream.seek(0)); 89 output_signed = MUST(stream.read_value<LEB128<i32>>()); 90 EXPECT_EQ(output_signed, ((static_cast<i32>(j) << 7) + (i & 0x7F)) | (-1 & (~0x3FFF))); 91 } 92 93 // MSB set on last byte, but input too short 94 for (u16 j = 0x80; j <= 0xFF; ++j) { 95 buf[1] = static_cast<u8>(j); 96 97 MUST(stream.seek(0)); 98 EXPECT(stream.read_value<LEB128<u32>>().is_error()); 99 100 MUST(stream.seek(0)); 101 EXPECT(stream.read_value<LEB128<i32>>().is_error()); 102 } 103 } 104} 105 106TEST_CASE(overflow_sizeof_output_unsigned) 107{ 108 u8 u32_max_plus_one[] = { 0x80, 0x80, 0x80, 0x80, 0x10 }; 109 { 110 FixedMemoryStream stream { ReadonlyBytes { u32_max_plus_one, sizeof(u32_max_plus_one) } }; 111 EXPECT(stream.read_value<LEB128<u32>>().is_error()); 112 113 MUST(stream.seek(0)); 114 u64 out64 = MUST(stream.read_value<LEB128<u64>>()); 115 EXPECT_EQ(out64, static_cast<u64>(NumericLimits<u32>::max()) + 1); 116 } 117 118 u8 u32_max[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x0F }; 119 { 120 FixedMemoryStream stream { ReadonlyBytes { u32_max, sizeof(u32_max) } }; 121 u32 out = MUST(stream.read_value<LEB128<u32>>()); 122 EXPECT_EQ(out, NumericLimits<u32>::max()); 123 124 MUST(stream.seek(0)); 125 u64 out64 = MUST(stream.read_value<LEB128<u64>>()); 126 EXPECT_EQ(out64, NumericLimits<u32>::max()); 127 } 128} 129 130TEST_CASE(overflow_sizeof_output_signed) 131{ 132 u8 i32_max_plus_one[] = { 0x80, 0x80, 0x80, 0x80, 0x08 }; 133 { 134 FixedMemoryStream stream { ReadonlyBytes { i32_max_plus_one, sizeof(i32_max_plus_one) } }; 135 EXPECT(stream.read_value<LEB128<i32>>().is_error()); 136 137 MUST(stream.seek(0)); 138 i64 out64 = MUST(stream.read_value<LEB128<i64>>()); 139 EXPECT_EQ(out64, static_cast<i64>(NumericLimits<i32>::max()) + 1); 140 } 141 142 u8 i32_max[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x07 }; 143 { 144 FixedMemoryStream stream { ReadonlyBytes { i32_max, sizeof(i32_max) } }; 145 i32 out = MUST(stream.read_value<LEB128<i32>>()); 146 EXPECT_EQ(out, NumericLimits<i32>::max()); 147 148 MUST(stream.seek(0)); 149 i64 out64 = MUST(stream.read_value<LEB128<i64>>()); 150 EXPECT_EQ(out64, NumericLimits<i32>::max()); 151 } 152 153 u8 i32_min_minus_one[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x77 }; 154 { 155 FixedMemoryStream stream { ReadonlyBytes { i32_min_minus_one, sizeof(i32_min_minus_one) } }; 156 EXPECT(stream.read_value<LEB128<i32>>().is_error()); 157 158 MUST(stream.seek(0)); 159 i64 out64 = MUST(stream.read_value<LEB128<i64>>()); 160 EXPECT_EQ(out64, static_cast<i64>(NumericLimits<i32>::min()) - 1); 161 } 162 163 u8 i32_min[] = { 0x80, 0x80, 0x80, 0x80, 0x78 }; 164 { 165 FixedMemoryStream stream { ReadonlyBytes { i32_min, sizeof(i32_min) } }; 166 i32 out = MUST(stream.read_value<LEB128<i32>>()); 167 EXPECT_EQ(out, NumericLimits<i32>::min()); 168 169 MUST(stream.seek(0)); 170 i64 out64 = MUST(stream.read_value<LEB128<i64>>()); 171 EXPECT_EQ(out64, NumericLimits<i32>::min()); 172 } 173}