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
Reader(MemoryBufferRef InputBuffer)23 Reader::Reader(MemoryBufferRef InputBuffer)
24 : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
25 End(InputBuffer.getBufferEnd()) {}
26
Reader(StringRef Input)27 Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
28
read(Object & Obj)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
readRaw(Object & Obj)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
readInt(Object & Obj)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
readUInt(Object & Obj)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
readLength(Object & Obj)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
readExt(Object & Obj)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
createRaw(Object & Obj,uint32_t Size)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
createExt(Object & Obj,uint32_t Size)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