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 = BitsToFloat(endian::read<uint32_t, Endianness>(Current)); 78 Current += sizeof(float); 79 return true; 80 case FirstByte::Float64: 81 Obj.Kind = Type::Float; 82 if (sizeof(double) > remainingSpace()) 83 return make_error<StringError>( 84 "Invalid Float64 with insufficient payload", 85 std::make_error_code(std::errc::invalid_argument)); 86 Obj.Float = BitsToDouble(endian::read<uint64_t, Endianness>(Current)); 87 Current += sizeof(double); 88 return true; 89 case FirstByte::Str8: 90 Obj.Kind = Type::String; 91 return readRaw<uint8_t>(Obj); 92 case FirstByte::Str16: 93 Obj.Kind = Type::String; 94 return readRaw<uint16_t>(Obj); 95 case FirstByte::Str32: 96 Obj.Kind = Type::String; 97 return readRaw<uint32_t>(Obj); 98 case FirstByte::Bin8: 99 Obj.Kind = Type::Binary; 100 return readRaw<uint8_t>(Obj); 101 case FirstByte::Bin16: 102 Obj.Kind = Type::Binary; 103 return readRaw<uint16_t>(Obj); 104 case FirstByte::Bin32: 105 Obj.Kind = Type::Binary; 106 return readRaw<uint32_t>(Obj); 107 case FirstByte::Array16: 108 Obj.Kind = Type::Array; 109 return readLength<uint16_t>(Obj); 110 case FirstByte::Array32: 111 Obj.Kind = Type::Array; 112 return readLength<uint32_t>(Obj); 113 case FirstByte::Map16: 114 Obj.Kind = Type::Map; 115 return readLength<uint16_t>(Obj); 116 case FirstByte::Map32: 117 Obj.Kind = Type::Map; 118 return readLength<uint32_t>(Obj); 119 case FirstByte::FixExt1: 120 Obj.Kind = Type::Extension; 121 return createExt(Obj, FixLen::Ext1); 122 case FirstByte::FixExt2: 123 Obj.Kind = Type::Extension; 124 return createExt(Obj, FixLen::Ext2); 125 case FirstByte::FixExt4: 126 Obj.Kind = Type::Extension; 127 return createExt(Obj, FixLen::Ext4); 128 case FirstByte::FixExt8: 129 Obj.Kind = Type::Extension; 130 return createExt(Obj, FixLen::Ext8); 131 case FirstByte::FixExt16: 132 Obj.Kind = Type::Extension; 133 return createExt(Obj, FixLen::Ext16); 134 case FirstByte::Ext8: 135 Obj.Kind = Type::Extension; 136 return readExt<uint8_t>(Obj); 137 case FirstByte::Ext16: 138 Obj.Kind = Type::Extension; 139 return readExt<uint16_t>(Obj); 140 case FirstByte::Ext32: 141 Obj.Kind = Type::Extension; 142 return readExt<uint32_t>(Obj); 143 } 144 145 if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) { 146 Obj.Kind = Type::Int; 147 int8_t I; 148 static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes"); 149 memcpy(&I, &FB, sizeof(FB)); 150 Obj.Int = I; 151 return true; 152 } 153 154 if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) { 155 Obj.Kind = Type::UInt; 156 Obj.UInt = FB; 157 return true; 158 } 159 160 if ((FB & FixBitsMask::String) == FixBits::String) { 161 Obj.Kind = Type::String; 162 uint8_t Size = FB & ~FixBitsMask::String; 163 return createRaw(Obj, Size); 164 } 165 166 if ((FB & FixBitsMask::Array) == FixBits::Array) { 167 Obj.Kind = Type::Array; 168 Obj.Length = FB & ~FixBitsMask::Array; 169 return true; 170 } 171 172 if ((FB & FixBitsMask::Map) == FixBits::Map) { 173 Obj.Kind = Type::Map; 174 Obj.Length = FB & ~FixBitsMask::Map; 175 return true; 176 } 177 178 return make_error<StringError>( 179 "Invalid first byte", std::make_error_code(std::errc::invalid_argument)); 180 } 181 182 template <class T> Expected<bool> Reader::readRaw(Object &Obj) { 183 if (sizeof(T) > remainingSpace()) 184 return make_error<StringError>( 185 "Invalid Raw with insufficient payload", 186 std::make_error_code(std::errc::invalid_argument)); 187 T Size = endian::read<T, Endianness>(Current); 188 Current += sizeof(T); 189 return createRaw(Obj, Size); 190 } 191 192 template <class T> Expected<bool> Reader::readInt(Object &Obj) { 193 if (sizeof(T) > remainingSpace()) 194 return make_error<StringError>( 195 "Invalid Int with insufficient payload", 196 std::make_error_code(std::errc::invalid_argument)); 197 Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current)); 198 Current += sizeof(T); 199 return true; 200 } 201 202 template <class T> Expected<bool> Reader::readUInt(Object &Obj) { 203 if (sizeof(T) > remainingSpace()) 204 return make_error<StringError>( 205 "Invalid Int with insufficient payload", 206 std::make_error_code(std::errc::invalid_argument)); 207 Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current)); 208 Current += sizeof(T); 209 return true; 210 } 211 212 template <class T> Expected<bool> Reader::readLength(Object &Obj) { 213 if (sizeof(T) > remainingSpace()) 214 return make_error<StringError>( 215 "Invalid Map/Array with invalid length", 216 std::make_error_code(std::errc::invalid_argument)); 217 Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current)); 218 Current += sizeof(T); 219 return true; 220 } 221 222 template <class T> Expected<bool> Reader::readExt(Object &Obj) { 223 if (sizeof(T) > remainingSpace()) 224 return make_error<StringError>( 225 "Invalid Ext with invalid length", 226 std::make_error_code(std::errc::invalid_argument)); 227 T Size = endian::read<T, Endianness>(Current); 228 Current += sizeof(T); 229 return createExt(Obj, Size); 230 } 231 232 Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) { 233 if (Size > remainingSpace()) 234 return make_error<StringError>( 235 "Invalid Raw with insufficient payload", 236 std::make_error_code(std::errc::invalid_argument)); 237 Obj.Raw = StringRef(Current, Size); 238 Current += Size; 239 return true; 240 } 241 242 Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) { 243 if (Current == End) 244 return make_error<StringError>( 245 "Invalid Ext with no type", 246 std::make_error_code(std::errc::invalid_argument)); 247 Obj.Extension.Type = *Current++; 248 if (Size > remainingSpace()) 249 return make_error<StringError>( 250 "Invalid Ext with insufficient payload", 251 std::make_error_code(std::errc::invalid_argument)); 252 Obj.Extension.Bytes = StringRef(Current, Size); 253 Current += Size; 254 return true; 255 } 256