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
19using namespace llvm;
20using namespace llvm::support;
21using namespace msgpack;
22
23Reader::Reader(MemoryBufferRef InputBuffer)
24 : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
25 End(InputBuffer.getBufferEnd()) {}
26
27Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
28
29Expected<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 Args: "Invalid Float32 with insufficient payload",
76 Args: std::make_error_code(e: std::errc::invalid_argument));
77 Obj.Float =
78 llvm::bit_cast<float>(from: endian::read<uint32_t, Endianness>(P: 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 Args: "Invalid Float64 with insufficient payload",
86 Args: std::make_error_code(e: std::errc::invalid_argument));
87 Obj.Float =
88 llvm::bit_cast<double>(from: endian::read<uint64_t, Endianness>(P: 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, Size: FixLen::Ext1);
124 case FirstByte::FixExt2:
125 Obj.Kind = Type::Extension;
126 return createExt(Obj, Size: FixLen::Ext2);
127 case FirstByte::FixExt4:
128 Obj.Kind = Type::Extension;
129 return createExt(Obj, Size: FixLen::Ext4);
130 case FirstByte::FixExt8:
131 Obj.Kind = Type::Extension;
132 return createExt(Obj, Size: FixLen::Ext8);
133 case FirstByte::FixExt16:
134 Obj.Kind = Type::Extension;
135 return createExt(Obj, Size: 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(dest: &I, src: &FB, n: 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 Args: "Invalid first byte", Args: std::make_error_code(e: std::errc::invalid_argument));
182}
183
184template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
185 if (sizeof(T) > remainingSpace())
186 return make_error<StringError>(
187 Args: "Invalid Raw with insufficient payload",
188 Args: std::make_error_code(e: std::errc::invalid_argument));
189 T Size = endian::read<T, Endianness>(Current);
190 Current += sizeof(T);
191 return createRaw(Obj, Size);
192}
193
194template <class T> Expected<bool> Reader::readInt(Object &Obj) {
195 if (sizeof(T) > remainingSpace())
196 return make_error<StringError>(
197 Args: "Invalid Int with insufficient payload",
198 Args: std::make_error_code(e: 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
204template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
205 if (sizeof(T) > remainingSpace())
206 return make_error<StringError>(
207 Args: "Invalid Int with insufficient payload",
208 Args: std::make_error_code(e: 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
214template <class T> Expected<bool> Reader::readLength(Object &Obj) {
215 if (sizeof(T) > remainingSpace())
216 return make_error<StringError>(
217 Args: "Invalid Map/Array with invalid length",
218 Args: std::make_error_code(e: 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
224template <class T> Expected<bool> Reader::readExt(Object &Obj) {
225 if (sizeof(T) > remainingSpace())
226 return make_error<StringError>(
227 Args: "Invalid Ext with invalid length",
228 Args: std::make_error_code(e: std::errc::invalid_argument));
229 T Size = endian::read<T, Endianness>(Current);
230 Current += sizeof(T);
231 return createExt(Obj, Size);
232}
233
234Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
235 if (Size > remainingSpace())
236 return make_error<StringError>(
237 Args: "Invalid Raw with insufficient payload",
238 Args: std::make_error_code(e: std::errc::invalid_argument));
239 Obj.Raw = StringRef(Current, Size);
240 Current += Size;
241 return true;
242}
243
244Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
245 if (Current == End)
246 return make_error<StringError>(
247 Args: "Invalid Ext with no type",
248 Args: std::make_error_code(e: std::errc::invalid_argument));
249 Obj.Extension.Type = *Current++;
250 if (Size > remainingSpace())
251 return make_error<StringError>(
252 Args: "Invalid Ext with insufficient payload",
253 Args: std::make_error_code(e: std::errc::invalid_argument));
254 Obj.Extension.Bytes = StringRef(Current, Size);
255 Current += Size;
256 return true;
257}
258