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