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