Coverage Report

Created: 2024-09-08 06:19

/src/arduinojson/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp
Line
Count
Source (jump to first uncovered line)
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2024, Benoit BLANCHON
3
// MIT License
4
5
#pragma once
6
7
#include <ArduinoJson/Deserialization/deserialize.hpp>
8
#include <ArduinoJson/Memory/ResourceManager.hpp>
9
#include <ArduinoJson/Memory/StringBuffer.hpp>
10
#include <ArduinoJson/MsgPack/endianness.hpp>
11
#include <ArduinoJson/MsgPack/ieee754.hpp>
12
#include <ArduinoJson/Polyfills/type_traits.hpp>
13
#include <ArduinoJson/Variant/VariantData.hpp>
14
15
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
16
17
template <typename TReader>
18
class MsgPackDeserializer {
19
 public:
20
  MsgPackDeserializer(ResourceManager* resources, TReader reader)
21
      : resources_(resources),
22
        reader_(reader),
23
        stringBuffer_(resources),
24
1.46k
        foundSomething_(false) {}
25
26
  template <typename TFilter>
27
  DeserializationError parse(VariantData& variant, TFilter filter,
28
1.46k
                             DeserializationOption::NestingLimit nestingLimit) {
29
1.46k
    DeserializationError::Code err;
30
1.46k
    err = parseVariant(&variant, filter, nestingLimit);
31
1.46k
    return foundSomething_ ? err : DeserializationError::EmptyInput;
32
1.46k
  }
33
34
 private:
35
  template <typename TFilter>
36
  DeserializationError::Code parseVariant(
37
      VariantData* variant, TFilter filter,
38
14.6k
      DeserializationOption::NestingLimit nestingLimit) {
39
14.6k
    DeserializationError::Code err;
40
41
14.6k
    uint8_t header[5];
42
14.6k
    err = readBytes(header, 1);
43
14.6k
    if (err)
44
235
      return err;
45
46
14.4k
    const uint8_t& code = header[0];
47
48
14.4k
    foundSomething_ = true;
49
50
14.4k
    bool allowValue = filter.allowValue();
51
52
14.4k
    if (allowValue) {
53
      // callers pass a null pointer only when value must be ignored
54
14.4k
      ARDUINOJSON_ASSERT(variant != 0);
55
14.4k
    }
56
57
14.4k
    if (code >= 0xcc && code <= 0xd3) {
58
865
      auto width = uint8_t(1U << ((code - 0xcc) % 4));
59
865
      if (allowValue)
60
865
        return readInteger(variant, width, code >= 0xd0);
61
0
      else
62
0
        return skipBytes(width);
63
865
    }
64
65
13.5k
    switch (code) {
66
215
      case 0xc0:
67
        // already null
68
215
        return DeserializationError::Ok;
69
70
3
      case 0xc1:
71
3
        return DeserializationError::InvalidInput;
72
73
212
      case 0xc2:
74
416
      case 0xc3:
75
416
        if (allowValue)
76
416
          variant->setBoolean(code == 0xc3);
77
416
        return DeserializationError::Ok;
78
79
416
      case 0xca:
80
416
        if (allowValue)
81
416
          return readFloat<float>(variant);
82
0
        else
83
0
          return skipBytes(4);
84
85
150
      case 0xcb:
86
150
        if (allowValue)
87
150
          return readDouble<double>(variant);
88
0
        else
89
0
          return skipBytes(8);
90
13.5k
    }
91
92
12.3k
    if (code <= 0x7f || code >= 0xe0) {  // fixint
93
3.97k
      if (allowValue)
94
3.97k
        variant->setInteger(static_cast<int8_t>(code), resources_);
95
3.97k
      return DeserializationError::Ok;
96
3.97k
    }
97
98
8.39k
    uint8_t sizeBytes = 0;
99
8.39k
    size_t size = 0;
100
8.39k
    bool isExtension = code >= 0xc7 && code <= 0xc9;
101
102
8.39k
    switch (code) {
103
455
      case 0xc4:  // bin 8
104
573
      case 0xc7:  // ext 8
105
940
      case 0xd9:  // str 8
106
940
        sizeBytes = 1;
107
940
        break;
108
109
94
      case 0xc5:  // bin 16
110
171
      case 0xc8:  // ext 16
111
330
      case 0xda:  // str 16
112
534
      case 0xdc:  // array 16
113
699
      case 0xde:  // map 16
114
699
        sizeBytes = 2;
115
699
        break;
116
117
105
      case 0xc6:  // bin 32
118
183
      case 0xc9:  // ext 32
119
384
      case 0xdb:  // str 32
120
597
      case 0xdd:  // array 32
121
746
      case 0xdf:  // map 32
122
746
        sizeBytes = 4;
123
746
        break;
124
8.39k
    }
125
126
8.39k
    if (code >= 0xd4 && code <= 0xd8) {  // fixext
127
173
      size = size_t(1) << (code - 0xd4);
128
173
      isExtension = true;
129
173
    }
130
131
8.39k
    switch (code & 0xf0) {
132
2.67k
      case 0x90:  // fixarray
133
3.56k
      case 0x80:  // fixmap
134
3.56k
        size = code & 0x0F;
135
3.56k
        break;
136
8.39k
    }
137
138
8.39k
    switch (code & 0xe0) {
139
2.27k
      case 0xa0:  // fixstr
140
2.27k
        size = code & 0x1f;
141
2.27k
        break;
142
8.39k
    }
143
144
8.39k
    if (sizeBytes) {
145
2.38k
      err = readBytes(header + 1, sizeBytes);
146
2.38k
      if (err)
147
102
        return err;
148
149
2.28k
      uint32_t size32 = 0;
150
7.34k
      for (uint8_t i = 0; i < sizeBytes; i++)
151
5.05k
        size32 = (size32 << 8) | header[i + 1];
152
153
2.28k
      size = size_t(size32);
154
2.28k
      if (size < size32)                        // integer overflow
155
0
        return DeserializationError::NoMemory;  // (not testable on 32/64-bit)
156
2.28k
    }
157
158
    // array 16, 32 and fixarray
159
8.29k
    if (code == 0xdc || code == 0xdd || (code & 0xf0) == 0x90)
160
3.07k
      return readArray(variant, size, filter, nestingLimit);
161
162
    // map 16, 32 and fixmap
163
5.22k
    if (code == 0xde || code == 0xdf || (code & 0xf0) == 0x80)
164
1.18k
      return readObject(variant, size, filter, nestingLimit);
165
166
    // str 8, 16, 32 and fixstr
167
4.03k
    if (code == 0xd9 || code == 0xda || code == 0xdb || (code & 0xe0) == 0xa0) {
168
2.98k
      if (allowValue)
169
2.98k
        return readString(variant, size);
170
0
      else
171
0
        return skipBytes(size);
172
2.98k
    }
173
174
1.05k
    if (isExtension)
175
425
      size++;  // to include the type
176
177
1.05k
    if (allowValue)
178
1.05k
      return readRawString(variant, header, uint8_t(1 + sizeBytes), size);
179
0
    else
180
0
      return skipBytes(size);
181
1.05k
  }
182
183
2.76k
  DeserializationError::Code readByte(uint8_t& value) {
184
2.76k
    int c = reader_.read();
185
2.76k
    if (c < 0)
186
74
      return DeserializationError::IncompleteInput;
187
2.69k
    value = static_cast<uint8_t>(c);
188
2.69k
    return DeserializationError::Ok;
189
2.76k
  }
190
191
24.5k
  DeserializationError::Code readBytes(void* p, size_t n) {
192
24.5k
    if (reader_.readBytes(reinterpret_cast<char*>(p), n) == n)
193
23.9k
      return DeserializationError::Ok;
194
568
    return DeserializationError::IncompleteInput;
195
24.5k
  }
196
197
  template <typename T>
198
566
  DeserializationError::Code readBytes(T& value) {
199
566
    return readBytes(&value, sizeof(value));
200
566
  }
ArduinoJson::V710HB42::DeserializationError::Code ArduinoJson::V710HB42::detail::MsgPackDeserializer<ArduinoJson::V710HB42::detail::BoundedReader<unsigned char const*, void> >::readBytes<float>(float&)
Line
Count
Source
198
416
  DeserializationError::Code readBytes(T& value) {
199
416
    return readBytes(&value, sizeof(value));
200
416
  }
ArduinoJson::V710HB42::DeserializationError::Code ArduinoJson::V710HB42::detail::MsgPackDeserializer<ArduinoJson::V710HB42::detail::BoundedReader<unsigned char const*, void> >::readBytes<double>(double&)
Line
Count
Source
198
150
  DeserializationError::Code readBytes(T& value) {
199
150
    return readBytes(&value, sizeof(value));
200
150
  }
201
202
0
  DeserializationError::Code skipBytes(size_t n) {
203
0
    for (; n; --n) {
204
0
      if (reader_.read() < 0)
205
0
        return DeserializationError::IncompleteInput;
206
0
    }
207
0
    return DeserializationError::Ok;
208
0
  }
209
210
  DeserializationError::Code readInteger(VariantData* variant, uint8_t width,
211
865
                                         bool isSigned) {
212
865
    uint8_t buffer[8];
213
214
865
    auto err = readBytes(buffer, width);
215
865
    if (err)
216
17
      return err;
217
218
848
    union {
219
848
      int64_t signedValue;
220
848
      uint64_t unsignedValue;
221
848
    };
222
223
848
    if (isSigned)
224
441
      signedValue = static_cast<int8_t>(buffer[0]);  // propagate sign bit
225
407
    else
226
407
      unsignedValue = static_cast<uint8_t>(buffer[0]);
227
228
3.62k
    for (uint8_t i = 1; i < width; i++)
229
2.77k
      unsignedValue = (unsignedValue << 8) | buffer[i];
230
231
848
    if (isSigned) {
232
441
      auto truncatedValue = static_cast<JsonInteger>(signedValue);
233
441
      if (truncatedValue == signedValue) {
234
441
        if (!variant->setInteger(truncatedValue, resources_))
235
0
          return DeserializationError::NoMemory;
236
441
      }
237
      // else set null on overflow
238
441
    } else {
239
407
      auto truncatedValue = static_cast<JsonUInt>(unsignedValue);
240
407
      if (truncatedValue == unsignedValue)
241
407
        if (!variant->setInteger(truncatedValue, resources_))
242
0
          return DeserializationError::NoMemory;
243
      // else set null on overflow
244
407
    }
245
246
848
    return DeserializationError::Ok;
247
848
  }
248
249
  template <typename T>
250
  enable_if_t<sizeof(T) == 4, DeserializationError::Code> readFloat(
251
416
      VariantData* variant) {
252
416
    DeserializationError::Code err;
253
416
    T value;
254
255
416
    err = readBytes(value);
256
416
    if (err)
257
8
      return err;
258
259
408
    fixEndianness(value);
260
408
    variant->setFloat(value, resources_);
261
262
408
    return DeserializationError::Ok;
263
416
  }
264
265
  template <typename T>
266
  enable_if_t<sizeof(T) == 8, DeserializationError::Code> readDouble(
267
150
      VariantData* variant) {
268
150
    DeserializationError::Code err;
269
150
    T value;
270
271
150
    err = readBytes(value);
272
150
    if (err)
273
14
      return err;
274
275
136
    fixEndianness(value);
276
136
    if (variant->setFloat(value, resources_))
277
136
      return DeserializationError::Ok;
278
0
    else
279
0
      return DeserializationError::NoMemory;
280
136
  }
281
282
  template <typename T>
283
  enable_if_t<sizeof(T) == 4, DeserializationError::Code> readDouble(
284
      VariantData* variant) {
285
    DeserializationError::Code err;
286
    uint8_t i[8];  // input is 8 bytes
287
    T value;       // output is 4 bytes
288
    uint8_t* o = reinterpret_cast<uint8_t*>(&value);
289
290
    err = readBytes(i, 8);
291
    if (err)
292
      return err;
293
294
    doubleToFloat(i, o);
295
    fixEndianness(value);
296
    variant->setFloat(value, resources_);
297
298
    return DeserializationError::Ok;
299
  }
300
301
2.98k
  DeserializationError::Code readString(VariantData* variant, size_t n) {
302
2.98k
    DeserializationError::Code err;
303
304
2.98k
    err = readString(n);
305
2.98k
    if (err)
306
112
      return err;
307
308
2.86k
    variant->setOwnedString(stringBuffer_.save());
309
2.86k
    return DeserializationError::Ok;
310
2.98k
  }
311
312
5.11k
  DeserializationError::Code readString(size_t n) {
313
5.11k
    char* p = stringBuffer_.reserve(n);
314
5.11k
    if (!p)
315
39
      return DeserializationError::NoMemory;
316
317
5.07k
    return readBytes(p, n);
318
5.11k
  }
319
320
  DeserializationError::Code readRawString(VariantData* variant,
321
                                           const void* header,
322
1.05k
                                           uint8_t headerSize, size_t n) {
323
1.05k
    auto totalSize = size_t(headerSize + n);
324
1.05k
    if (totalSize < n)                        // integer overflow
325
0
      return DeserializationError::NoMemory;  // (not testable on 64-bit)
326
327
1.05k
    char* p = stringBuffer_.reserve(totalSize);
328
1.05k
    if (!p)
329
52
      return DeserializationError::NoMemory;
330
331
1.00k
    memcpy(p, header, headerSize);
332
333
1.00k
    auto err = readBytes(p + headerSize, n);
334
1.00k
    if (err)
335
97
      return err;
336
337
909
    variant->setRawString(stringBuffer_.save());
338
909
    return DeserializationError::Ok;
339
1.00k
  }
340
341
  template <typename TFilter>
342
  DeserializationError::Code readArray(
343
      VariantData* variant, size_t n, TFilter filter,
344
3.07k
      DeserializationOption::NestingLimit nestingLimit) {
345
3.07k
    DeserializationError::Code err;
346
347
3.07k
    if (nestingLimit.reached())
348
4
      return DeserializationError::TooDeep;
349
350
3.07k
    bool allowArray = filter.allowArray();
351
352
3.07k
    ArrayData* array;
353
3.07k
    if (allowArray) {
354
3.07k
      ARDUINOJSON_ASSERT(variant != 0);
355
3.07k
      array = &variant->toArray();
356
3.07k
    } else {
357
0
      array = 0;
358
0
    }
359
360
3.07k
    TFilter elementFilter = filter[0U];
361
362
13.4k
    for (; n; --n) {
363
11.0k
      VariantData* value;
364
365
11.0k
      if (elementFilter.allow()) {
366
11.0k
        ARDUINOJSON_ASSERT(array != 0);
367
11.0k
        value = array->addElement(resources_);
368
11.0k
        if (!value)
369
0
          return DeserializationError::NoMemory;
370
11.0k
      } else {
371
0
        value = 0;
372
0
      }
373
374
11.0k
      err = parseVariant(value, elementFilter, nestingLimit.decrement());
375
11.0k
      if (err)
376
743
        return err;
377
11.0k
    }
378
379
2.32k
    return DeserializationError::Ok;
380
3.07k
  }
381
382
  template <typename TFilter>
383
  DeserializationError::Code readObject(
384
      VariantData* variant, size_t n, TFilter filter,
385
1.18k
      DeserializationOption::NestingLimit nestingLimit) {
386
1.18k
    DeserializationError::Code err;
387
388
1.18k
    if (nestingLimit.reached())
389
1
      return DeserializationError::TooDeep;
390
391
1.18k
    ObjectData* object;
392
1.18k
    if (filter.allowObject()) {
393
1.18k
      ARDUINOJSON_ASSERT(variant != 0);
394
1.18k
      object = &variant->toObject();
395
1.18k
    } else {
396
0
      object = 0;
397
0
    }
398
399
3.16k
    for (; n; --n) {
400
2.22k
      err = readKey();
401
2.22k
      if (err)
402
116
        return err;
403
404
2.10k
      JsonString key = stringBuffer_.str();
405
2.10k
      TFilter memberFilter = filter[key.c_str()];
406
2.10k
      VariantData* member;
407
408
2.10k
      if (memberFilter.allow()) {
409
2.10k
        ARDUINOJSON_ASSERT(object != 0);
410
411
        // Save key in memory pool.
412
2.10k
        auto savedKey = stringBuffer_.save();
413
414
2.10k
        member = object->addMember(savedKey, resources_);
415
2.10k
        if (!member)
416
0
          return DeserializationError::NoMemory;
417
2.10k
      } else {
418
0
        member = 0;
419
0
      }
420
421
2.10k
      err = parseVariant(member, memberFilter, nestingLimit.decrement());
422
2.10k
      if (err)
423
120
        return err;
424
2.10k
    }
425
426
945
    return DeserializationError::Ok;
427
1.18k
  }
428
429
2.22k
  DeserializationError::Code readKey() {
430
2.22k
    DeserializationError::Code err;
431
2.22k
    uint8_t code;
432
433
2.22k
    err = readByte(code);
434
2.22k
    if (err)
435
61
      return err;
436
437
2.16k
    if ((code & 0xe0) == 0xa0)
438
1.94k
      return readString(code & 0x1f);
439
440
216
    if (code >= 0xd9 && code <= 0xdb) {
441
196
      uint8_t sizeBytes = uint8_t(1U << (code - 0xd9));
442
196
      uint32_t size = 0;
443
726
      for (uint8_t i = 0; i < sizeBytes; i++) {
444
543
        err = readByte(code);
445
543
        if (err)
446
13
          return err;
447
530
        size = (size << 8) | code;
448
530
      }
449
183
      return readString(size);
450
196
    }
451
452
20
    return DeserializationError::InvalidInput;
453
216
  }
454
455
  ResourceManager* resources_;
456
  TReader reader_;
457
  StringBuffer stringBuffer_;
458
  bool foundSomething_;
459
};
460
461
ARDUINOJSON_END_PRIVATE_NAMESPACE
462
463
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
464
465
// Parses a MessagePack input and puts the result in a JsonDocument.
466
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
467
template <typename TDestination, typename... Args>
468
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
469
                    DeserializationError>
470
deserializeMsgPack(TDestination&& dst, Args&&... args) {
471
  using namespace detail;
472
  return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
473
                                          detail::forward<Args>(args)...);
474
}
475
476
// Parses a MessagePack input and puts the result in a JsonDocument.
477
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
478
template <typename TDestination, typename TChar, typename... Args>
479
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
480
                    DeserializationError>
481
1.46k
deserializeMsgPack(TDestination&& dst, TChar* input, Args&&... args) {
482
1.46k
  using namespace detail;
483
1.46k
  return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
484
1.46k
                                          input,
485
1.46k
                                          detail::forward<Args>(args)...);
486
1.46k
}
487
488
ARDUINOJSON_END_PUBLIC_NAMESPACE