1 //===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file implements a MessagePack reader. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/BinaryFormat/MsgPackReader.h" 15 #include "llvm/BinaryFormat/MsgPack.h" 16 #include "llvm/Support/Endian.h" 17 #include "llvm/Support/MathExtras.h" 18 19 using namespace llvm; 20 using namespace llvm::support; 21 using namespace msgpack; 22 23 Reader::Reader(MemoryBufferRef InputBuffer) 24 : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()), 25 End(InputBuffer.getBufferEnd()) {} 26 27 Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {} 28 29 Expected<bool> Reader::read(Object &Obj) { 30 if (Current == End) 31 return false; 32 33 uint8_t FB = static_cast<uint8_t>(*Current++); 34 35 switch (FB) { 36 case FirstByte::Nil: 37 Obj.Kind = Type::Nil; 38 return true; 39 case FirstByte::True: 40 Obj.Kind = Type::Boolean; 41 Obj.Bool = true; 42 return true; 43 case FirstByte::False: 44 Obj.Kind = Type::Boolean; 45 Obj.Bool = false; 46 return true; 47 case FirstByte::Int8: 48 Obj.Kind = Type::Int; 49 return readInt<int8_t>(Obj); 50 case FirstByte::Int16: 51 Obj.Kind = Type::Int; 52 return readInt<int16_t>(Obj); 53 case FirstByte::Int32: 54 Obj.Kind = Type::Int; 55 return readInt<int32_t>(Obj); 56 case FirstByte::Int64: 57 Obj.Kind = Type::Int; 58 return readInt<int64_t>(Obj); 59 case FirstByte::UInt8: 60 Obj.Kind = Type::UInt; 61 return readUInt<uint8_t>(Obj); 62 case FirstByte::UInt16: 63 Obj.Kind = Type::UInt; 64 return readUInt<uint16_t>(Obj); 65 case FirstByte::UInt32: 66 Obj.Kind = Type::UInt; 67 return readUInt<uint32_t>(Obj); 68 case FirstByte::UInt64: 69 Obj.Kind = Type::UInt; 70 return readUInt<uint64_t>(Obj); 71 case FirstByte::Float32: 72 Obj.Kind = Type::Float; 73 if (sizeof(float) > remainingSpace()) 74 return make_error<StringError>( 75 "Invalid Float32 with insufficient payload", 76 std::make_error_code(std::errc::invalid_argument)); 77 Obj.Float = 78 llvm::bit_cast<float>(endian::read<uint32_t, Endianness>(Current)); 79 Current += sizeof(float); 80 return true; 81 case FirstByte::Float64: 82 Obj.Kind = Type::Float; 83 if (sizeof(double) > remainingSpace()) 84 return make_error<StringError>( 85 "Invalid Float64 with insufficient payload", 86 std::make_error_code(std::errc::invalid_argument)); 87 Obj.Float = 88 llvm::bit_cast<double>(endian::read<uint64_t, Endianness>(Current)); 89 Current += sizeof(double); 90 return true; 91 case FirstByte::Str8: 92 Obj.Kind = Type::String; 93 return readRaw<uint8_t>(Obj); 94 case FirstByte::Str16: 95 Obj.Kind = Type::String; 96 return readRaw<uint16_t>(Obj); 97 case FirstByte::Str32: 98 Obj.Kind = Type::String; 99 return readRaw<uint32_t>(Obj); 100 case FirstByte::Bin8: 101 Obj.Kind = Type::Binary; 102 return readRaw<uint8_t>(Obj); 103 case FirstByte::Bin16: 104 Obj.Kind = Type::Binary; 105 return readRaw<uint16_t>(Obj); 106 case FirstByte::Bin32: 107 Obj.Kind = Type::Binary; 108 return readRaw<uint32_t>(Obj); 109 case FirstByte::Array16: 110 Obj.Kind = Type::Array; 111 return readLength<uint16_t>(Obj); 112 case FirstByte::Array32: 113 Obj.Kind = Type::Array; 114 return readLength<uint32_t>(Obj); 115 case FirstByte::Map16: 116 Obj.Kind = Type::Map; 117 return readLength<uint16_t>(Obj); 118 case FirstByte::Map32: 119 Obj.Kind = Type::Map; 120 return readLength<uint32_t>(Obj); 121 case FirstByte::FixExt1: 122 Obj.Kind = Type::Extension; 123 return createExt(Obj, FixLen::Ext1); 124 case FirstByte::FixExt2: 125 Obj.Kind = Type::Extension; 126 return createExt(Obj, FixLen::Ext2); 127 case FirstByte::FixExt4: 128 Obj.Kind = Type::Extension; 129 return createExt(Obj, FixLen::Ext4); 130 case FirstByte::FixExt8: 131 Obj.Kind = Type::Extension; 132 return createExt(Obj, FixLen::Ext8); 133 case FirstByte::FixExt16: 134 Obj.Kind = Type::Extension; 135 return createExt(Obj, FixLen::Ext16); 136 case FirstByte::Ext8: 137 Obj.Kind = Type::Extension; 138 return readExt<uint8_t>(Obj); 139 case FirstByte::Ext16: 140 Obj.Kind = Type::Extension; 141 return readExt<uint16_t>(Obj); 142 case FirstByte::Ext32: 143 Obj.Kind = Type::Extension; 144 return readExt<uint32_t>(Obj); 145 } 146 147 if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) { 148 Obj.Kind = Type::Int; 149 int8_t I; 150 static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes"); 151 memcpy(&I, &FB, sizeof(FB)); 152 Obj.Int = I; 153 return true; 154 } 155 156 if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) { 157 Obj.Kind = Type::UInt; 158 Obj.UInt = FB; 159 return true; 160 } 161 162 if ((FB & FixBitsMask::String) == FixBits::String) { 163 Obj.Kind = Type::String; 164 uint8_t Size = FB & ~FixBitsMask::String; 165 return createRaw(Obj, Size); 166 } 167 168 if ((FB & FixBitsMask::Array) == FixBits::Array) { 169 Obj.Kind = Type::Array; 170 Obj.Length = FB & ~FixBitsMask::Array; 171 return true; 172 } 173 174 if ((FB & FixBitsMask::Map) == FixBits::Map) { 175 Obj.Kind = Type::Map; 176 Obj.Length = FB & ~FixBitsMask::Map; 177 return true; 178 } 179 180 return make_error<StringError>( 181 "Invalid first byte", std::make_error_code(std::errc::invalid_argument)); 182 } 183 184 template <class T> Expected<bool> Reader::readRaw(Object &Obj) { 185 if (sizeof(T) > remainingSpace()) 186 return make_error<StringError>( 187 "Invalid Raw with insufficient payload", 188 std::make_error_code(std::errc::invalid_argument)); 189 T Size = endian::read<T, Endianness>(Current); 190 Current += sizeof(T); 191 return createRaw(Obj, Size); 192 } 193 194 template <class T> Expected<bool> Reader::readInt(Object &Obj) { 195 if (sizeof(T) > remainingSpace()) 196 return make_error<StringError>( 197 "Invalid Int with insufficient payload", 198 std::make_error_code(std::errc::invalid_argument)); 199 Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current)); 200 Current += sizeof(T); 201 return true; 202 } 203 204 template <class T> Expected<bool> Reader::readUInt(Object &Obj) { 205 if (sizeof(T) > remainingSpace()) 206 return make_error<StringError>( 207 "Invalid Int with insufficient payload", 208 std::make_error_code(std::errc::invalid_argument)); 209 Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current)); 210 Current += sizeof(T); 211 return true; 212 } 213 214 template <class T> Expected<bool> Reader::readLength(Object &Obj) { 215 if (sizeof(T) > remainingSpace()) 216 return make_error<StringError>( 217 "Invalid Map/Array with invalid length", 218 std::make_error_code(std::errc::invalid_argument)); 219 Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current)); 220 Current += sizeof(T); 221 return true; 222 } 223 224 template <class T> Expected<bool> Reader::readExt(Object &Obj) { 225 if (sizeof(T) > remainingSpace()) 226 return make_error<StringError>( 227 "Invalid Ext with invalid length", 228 std::make_error_code(std::errc::invalid_argument)); 229 T Size = endian::read<T, Endianness>(Current); 230 Current += sizeof(T); 231 return createExt(Obj, Size); 232 } 233 234 Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) { 235 if (Size > remainingSpace()) 236 return make_error<StringError>( 237 "Invalid Raw with insufficient payload", 238 std::make_error_code(std::errc::invalid_argument)); 239 Obj.Raw = StringRef(Current, Size); 240 Current += Size; 241 return true; 242 } 243 244 Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) { 245 if (Current == End) 246 return make_error<StringError>( 247 "Invalid Ext with no type", 248 std::make_error_code(std::errc::invalid_argument)); 249 Obj.Extension.Type = *Current++; 250 if (Size > remainingSpace()) 251 return make_error<StringError>( 252 "Invalid Ext with insufficient payload", 253 std::make_error_code(std::errc::invalid_argument)); 254 Obj.Extension.Bytes = StringRef(Current, Size); 255 Current += Size; 256 return true; 257 } 258