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