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