• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bblanchon / ArduinoJson / 8966923003

06 May 2024 09:23AM CUT coverage: 99.573%. Remained the same
8966923003

push

github

bblanchon
MsgPack: test failing string allocation

3734 of 3750 relevant lines covered (99.57%)

11103.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.62
/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp
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)
481✔
21
      : resources_(resources),
22
        reader_(reader),
23
        stringBuffer_(resources),
24
        foundSomething_(false) {}
481✔
25

26
  template <typename TFilter>
27
  DeserializationError parse(VariantData& variant, TFilter filter,
481✔
28
                             DeserializationOption::NestingLimit nestingLimit) {
29
    DeserializationError::Code err;
30
    err = parseVariant(&variant, filter, nestingLimit);
481✔
31
    return foundSomething_ ? err : DeserializationError::EmptyInput;
481✔
32
  }
33

34
 private:
35
  template <typename TFilter>
36
  DeserializationError::Code parseVariant(
830✔
37
      VariantData* variant, TFilter filter,
38
      DeserializationOption::NestingLimit nestingLimit) {
39
    DeserializationError::Code err;
40

41
    uint8_t code = 0;  // TODO: why do we need to initialize this variable?
830✔
42
    err = readByte(code);
830✔
43
    if (err)
830✔
44
      return err;
11✔
45

46
    foundSomething_ = true;
819✔
47

48
    bool allowValue = filter.allowValue();
819✔
49

50
    if (allowValue) {
51
      // callers pass a null pointer only when value must be ignored
52
      ARDUINOJSON_ASSERT(variant != 0);
53
    }
54

55
    size_t size = 0;
819✔
56

57
    switch (code) {
819✔
58
      case 0xc4:  // bin 8
30✔
59
      case 0xc7:  // ext 8
60
      case 0xd9:  // str 8
61
        uint8_t size8;
62
        err = readInteger(size8);
30✔
63
        size = size8;
30✔
64
        break;
30✔
65

66
      case 0xc5:  // bin 16
66✔
67
      case 0xc8:  // ext 16
68
      case 0xda:  // str 16
69
      case 0xdc:  // array 16
70
      case 0xde:  // map 16
71
        uint16_t size16;
72
        err = readInteger(size16);
66✔
73
        size = size16;
66✔
74
        break;
66✔
75

76
      case 0xc6:  // bin 32
79✔
77
      case 0xc9:  // ext 32
78
      case 0xdb:  // str 32
79
      case 0xdd:  // array 32
80
      case 0xdf:  // map 32
81
        uint32_t size32;
82
        err = readInteger(size32);
79✔
83
        size = size32;
79✔
84
        break;
79✔
85
    }
86

87
    if (err)
819✔
88
      return err;
39✔
89

90
    switch (code & 0xf0) {
780✔
91
      case 0x90:  // fixarray
195✔
92
      case 0x80:  // fixmap
93
        size = code & 0x0F;
195✔
94
        break;
195✔
95
    }
96

97
    switch (code & 0xe0) {
780✔
98
      case 0xa0:  // fixstr
45✔
99
        size = code & 0x1f;
45✔
100
        break;
45✔
101
    }
102

103
    // array 16, 32 and fixarray
104
    if (code == 0xdc || code == 0xdd || (code & 0xf0) == 0x90)
780✔
105
      return readArray(variant, size, filter, nestingLimit);
77✔
106

107
    // map 16, 32 and fixmap
108
    if (code == 0xde || code == 0xdf || (code & 0xf0) == 0x80)
703✔
109
      return readObject(variant, size, filter, nestingLimit);
180✔
110

111
    // str 8, 16, 32 and fixstr
112
    if (code == 0xd9 || code == 0xda || code == 0xdb || (code & 0xe0) == 0xa0) {
523✔
113
      if (allowValue)
86✔
114
        return readString(variant, size);
67✔
115
      else
116
        return skipBytes(size);
19✔
117
    }
118

119
    // bin 8, 16, 32
120
    if (code == 0xc4 || code == 0xc5 || code == 0xc6) {
437✔
121
      if (allowValue)
18✔
122
        return readBinary(variant, size);
15✔
123
      else
124
        return skipBytes(size);
3✔
125
    }
126

127
    // ext 8, 16, 32
128
    if (code == 0xc7 || code == 0xc8 || code == 0xc9)
419✔
129
      return skipBytes(size + 1);
15✔
130

131
    switch (code) {
404✔
132
      case 0xc0:
5✔
133
        // already null
134
        return DeserializationError::Ok;
5✔
135

136
      case 0xc1:
1✔
137
        return DeserializationError::InvalidInput;
1✔
138

139
      case 0xc2:
5✔
140
        if (allowValue)
5✔
141
          variant->setBoolean(false);
2✔
142
        return DeserializationError::Ok;
5✔
143

144
      case 0xc3:
5✔
145
        if (allowValue)
5✔
146
          variant->setBoolean(true);
2✔
147
        return DeserializationError::Ok;
5✔
148

149
      case 0xca:
20✔
150
        if (allowValue)
20✔
151
          return readFloat<float>(variant);
11✔
152
        else
153
          return skipBytes(4);
9✔
154

155
      case 0xcb:
19✔
156
        if (allowValue)
19✔
157
          return readDouble<double>(variant);
16✔
158
        else
159
          return skipBytes(8);
3✔
160

161
      case 0xcc:
10✔
162
        if (allowValue)
10✔
163
          return readInteger<uint8_t>(variant);
6✔
164
        else
165
          return skipBytes(1);
4✔
166

167
      case 0xcd:
11✔
168
        if (allowValue)
11✔
169
          return readInteger<uint16_t>(variant);
8✔
170
        else
171
          return skipBytes(2);
3✔
172

173
      case 0xce:
12✔
174
        if (allowValue)
12✔
175
          return readInteger<uint32_t>(variant);
9✔
176
        else
177
          return skipBytes(4);
3✔
178

179
      case 0xcf:
15✔
180
#if ARDUINOJSON_USE_LONG_LONG
181
        if (allowValue)
15✔
182
          return readInteger<uint64_t>(variant);
12✔
183
        else
184
          return skipBytes(8);
3✔
185
#else
186
        return skipBytes(8);  // not supported
187
#endif
188

189
      case 0xd0:
7✔
190
        if (allowValue)
7✔
191
          return readInteger<int8_t>(variant);
4✔
192
        else
193
          return skipBytes(1);
3✔
194

195
      case 0xd1:
9✔
196
        if (allowValue)
9✔
197
          return readInteger<int16_t>(variant);
6✔
198
        else
199
          return skipBytes(2);
3✔
200

201
      case 0xd2:
11✔
202
        if (allowValue)
11✔
203
          return readInteger<int32_t>(variant);
8✔
204
        else
205
          return skipBytes(4);
3✔
206

207
      case 0xd3:
15✔
208
#if ARDUINOJSON_USE_LONG_LONG
209
        if (allowValue)
15✔
210
          return readInteger<int64_t>(variant);
12✔
211
        else
212
          return skipBytes(8);  // not supported
3✔
213
#else
214
        return skipBytes(8);
215
#endif
216

217
      case 0xd4:  // fixext 1 (not supported)
5✔
218
        return skipBytes(2);
5✔
219

220
      case 0xd5:  // fixext 2 (not supported)
6✔
221
        return skipBytes(3);
6✔
222

223
      case 0xd6:  // fixext 4 (not supported)
8✔
224
        return skipBytes(5);
8✔
225

226
      case 0xd7:  // fixext 8 (not supported)
12✔
227
        return skipBytes(9);
12✔
228

229
      case 0xd8:  // fixext 16 (not supported)
20✔
230
        return skipBytes(17);
20✔
231

232
      default:  // fixint
208✔
233
        if (allowValue)
208✔
234
          variant->setInteger(static_cast<int8_t>(code));
160✔
235
        return DeserializationError::Ok;
208✔
236
    }
237
  }
238

239
  DeserializationError::Code readByte(uint8_t& value) {
1,119✔
240
    int c = reader_.read();
1,119✔
241
    if (c < 0)
1,119✔
242
      return DeserializationError::IncompleteInput;
15✔
243
    value = static_cast<uint8_t>(c);
1,104✔
244
    return DeserializationError::Ok;
1,104✔
245
  }
246

247
  DeserializationError::Code readBytes(void* p, size_t n) {
631✔
248
    if (reader_.readBytes(reinterpret_cast<char*>(p), n) == n)
631✔
249
      return DeserializationError::Ok;
508✔
250
    return DeserializationError::IncompleteInput;
123✔
251
  }
252

253
  template <typename T>
254
  DeserializationError::Code readBytes(T& value) {
279✔
255
    return readBytes(&value, sizeof(value));
279✔
256
  }
257

258
  DeserializationError::Code skipBytes(size_t n) {
723✔
259
    for (; n; --n) {
723✔
260
      if (reader_.read() < 0)
641✔
261
        return DeserializationError::IncompleteInput;
43✔
262
    }
263
    return DeserializationError::Ok;
82✔
264
  }
265

266
  template <typename T>
267
  DeserializationError::Code readInteger(T& value) {
252✔
268
    DeserializationError::Code err;
269

270
    err = readBytes(value);
252✔
271
    if (err)
252✔
272
      return err;
70✔
273

274
    fixEndianness(value);
182✔
275

276
    return DeserializationError::Ok;
182✔
277
  }
278

279
  template <typename T>
280
  DeserializationError::Code readInteger(VariantData* variant) {
65✔
281
    DeserializationError::Code err;
282
    T value;
283

284
    err = readInteger(value);
65✔
285
    if (err)
65✔
286
      return err;
30✔
287

288
    variant->setInteger(value);
35✔
289

290
    return DeserializationError::Ok;
35✔
291
  }
292

293
  template <typename T>
294
  typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
295
  readFloat(VariantData* variant) {
11✔
296
    DeserializationError::Code err;
297
    T value;
298

299
    err = readBytes(value);
11✔
300
    if (err)
11✔
301
      return err;
4✔
302

303
    fixEndianness(value);
7✔
304
    variant->setFloat(value);
7✔
305

306
    return DeserializationError::Ok;
7✔
307
  }
308

309
  template <typename T>
310
  typename enable_if<sizeof(T) == 8, DeserializationError::Code>::type
311
  readDouble(VariantData* variant) {
16✔
312
    DeserializationError::Code err;
313
    T value;
314

315
    err = readBytes(value);
16✔
316
    if (err)
16✔
317
      return err;
8✔
318

319
    fixEndianness(value);
8✔
320
    variant->setFloat(value);
8✔
321

322
    return DeserializationError::Ok;
8✔
323
  }
324

325
  template <typename T>
326
  typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
327
  readDouble(VariantData* variant) {
328
    DeserializationError::Code err;
329
    uint8_t i[8];  // input is 8 bytes
330
    T value;       // output is 4 bytes
331
    uint8_t* o = reinterpret_cast<uint8_t*>(&value);
332

333
    err = readBytes(i, 8);
334
    if (err)
335
      return err;
336

337
    doubleToFloat(i, o);
338
    fixEndianness(value);
339
    variant->setFloat(value);
340

341
    return DeserializationError::Ok;
342
  }
343

344
  template <typename T>
345
  DeserializationError::Code readString() {
12✔
346
    DeserializationError::Code err;
347
    T size;
348

349
    err = readInteger(size);
12✔
350
    if (err)
12✔
351
      return err;
1✔
352

353
    return readString(size);
11✔
354
  }
355

356
  DeserializationError::Code readString(VariantData* variant, size_t n) {
67✔
357
    DeserializationError::Code err;
358

359
    err = readString(n);
67✔
360
    if (err)
67✔
361
      return err;
33✔
362

363
    variant->setOwnedString(stringBuffer_.save());
34✔
364
    return DeserializationError::Ok;
34✔
365
  }
366

367
  DeserializationError::Code readString(size_t n) {
350✔
368
    char* p = stringBuffer_.reserve(n);
350✔
369
    if (!p)
350✔
370
      return DeserializationError::NoMemory;
10✔
371

372
    return readBytes(p, n);
340✔
373
  }
374

375
  DeserializationError::Code readBinary(VariantData* variant, size_t n) {
15✔
376
    uint8_t headerSize;
377

378
    if (n <= 0xFF) {
15✔
379
      headerSize = 2;
10✔
380
    }
381
#if ARDUINOJSON_STRING_LENGTH_SIZE >= 2
382
    else if (n <= 0xFFFF) {
5✔
383
      headerSize = 3;
4✔
384
    }
385
#endif
386
#if ARDUINOJSON_STRING_LENGTH_SIZE >= 4
387
    else {
388
      headerSize = 5;
1✔
389
    }
390
#else
391
    else {
392
      return DeserializationError::NoMemory;
×
393
    }
394
#endif
395

396
    char* p = stringBuffer_.reserve(headerSize + n);
15✔
397
    if (!p)
15✔
398
      return DeserializationError::NoMemory;
3✔
399

400
    if (n <= 0xFF) {
12✔
401
      *p++ = '\xc4';
8✔
402
      *p++ = char(n & 0xFF);
8✔
403
    } else if (n <= 0xFFFF) {
4✔
404
      *p++ = '\xc5';
3✔
405
      *p++ = char(n >> 8 & 0xFF);
3✔
406
      *p++ = char(n & 0xFF);
3✔
407
    } else {
408
      *p++ = '\xc6';
1✔
409
      *p++ = char(n >> 24 & 0xFF);
1✔
410
      *p++ = char(n >> 16 & 0xFF);
1✔
411
      *p++ = char(n >> 8 & 0xFF);
1✔
412
      *p++ = char(n & 0xFF);
1✔
413
    }
414

415
    auto err = readBytes(p, n);
12✔
416
    if (err)
12✔
417
      return err;
3✔
418

419
    variant->setRawString(stringBuffer_.save());
9✔
420
    return DeserializationError::Ok;
9✔
421
  }
422

423
  template <typename TFilter>
424
  DeserializationError::Code readArray(
77✔
425
      VariantData* variant, size_t n, TFilter filter,
426
      DeserializationOption::NestingLimit nestingLimit) {
427
    DeserializationError::Code err;
428

429
    if (nestingLimit.reached())
77✔
430
      return DeserializationError::TooDeep;
9✔
431

432
    bool allowArray = filter.allowArray();
68✔
433

434
    ArrayData* array;
435
    if (allowArray) {
68✔
436
      ARDUINOJSON_ASSERT(variant != 0);
437
      array = &variant->toArray();
56✔
438
    } else {
439
      array = 0;
12✔
440
    }
441

442
    TFilter elementFilter = filter[0U];
68✔
443

444
    for (; n; --n) {
140✔
445
      VariantData* value;
446

447
      if (elementFilter.allow()) {
87✔
448
        ARDUINOJSON_ASSERT(array != 0);
449
        value = array->addElement(resources_);
65✔
450
        if (!value)
65✔
451
          return DeserializationError::NoMemory;
3✔
452
      } else {
453
        value = 0;
22✔
454
      }
455

456
      err = parseVariant(value, elementFilter, nestingLimit.decrement());
84✔
457
      if (err)
84✔
458
        return err;
12✔
459
    }
460

461
    return DeserializationError::Ok;
53✔
462
  }
463

464
  template <typename TFilter>
465
  DeserializationError::Code readObject(
180✔
466
      VariantData* variant, size_t n, TFilter filter,
467
      DeserializationOption::NestingLimit nestingLimit) {
468
    DeserializationError::Code err;
469

470
    if (nestingLimit.reached())
180✔
471
      return DeserializationError::TooDeep;
7✔
472

473
    ObjectData* object;
474
    if (filter.allowObject()) {
173✔
475
      ARDUINOJSON_ASSERT(variant != 0);
476
      object = &variant->toObject();
163✔
477
    } else {
478
      object = 0;
10✔
479
    }
480

481
    for (; n; --n) {
422✔
482
      err = readKey();
289✔
483
      if (err)
289✔
484
        return err;
40✔
485

486
      JsonString key = stringBuffer_.str();
268✔
487
      TFilter memberFilter = filter[key.c_str()];
268✔
488
      VariantData* member;
489

490
      if (memberFilter.allow()) {
268✔
491
        ARDUINOJSON_ASSERT(object != 0);
492

493
        // Save key in memory pool.
494
        auto savedKey = stringBuffer_.save();
201✔
495

496
        member = object->addMember(savedKey, resources_);
201✔
497
        if (!member)
201✔
498
          return DeserializationError::NoMemory;
3✔
499
      } else {
500
        member = 0;
67✔
501
      }
502

503
      err = parseVariant(member, memberFilter, nestingLimit.decrement());
265✔
504
      if (err)
265✔
505
        return err;
16✔
506
    }
507

508
    return DeserializationError::Ok;
133✔
509
  }
510

511
  DeserializationError::Code readKey() {
289✔
512
    DeserializationError::Code err;
513
    uint8_t code;
514

515
    err = readByte(code);
289✔
516
    if (err)
289✔
517
      return err;
4✔
518

519
    if ((code & 0xe0) == 0xa0)
285✔
520
      return readString(code & 0x1f);
272✔
521

522
    switch (code) {
13✔
523
      case 0xd9:
8✔
524
        return readString<uint8_t>();
8✔
525

526
      case 0xda:
2✔
527
        return readString<uint16_t>();
2✔
528

529
      case 0xdb:
2✔
530
        return readString<uint32_t>();
2✔
531

532
      default:
1✔
533
        return DeserializationError::InvalidInput;
1✔
534
    }
535
  }
536

537
  ResourceManager* resources_;
538
  TReader reader_;
539
  StringBuffer stringBuffer_;
540
  bool foundSomething_;
541
};
542

543
ARDUINOJSON_END_PRIVATE_NAMESPACE
544

545
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
546

547
// Parses a MessagePack input and puts the result in a JsonDocument.
548
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
549
template <typename TDestination, typename... Args>
550
typename detail::enable_if<
551
    detail::is_deserialize_destination<TDestination>::value,
552
    DeserializationError>::type
553
deserializeMsgPack(TDestination&& dst, Args&&... args) {
38✔
554
  using namespace detail;
555
  return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
38✔
556
                                          detail::forward<Args>(args)...);
55✔
557
}
558

559
// Parses a MessagePack input and puts the result in a JsonDocument.
560
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
561
template <typename TDestination, typename TChar, typename... Args>
562
typename detail::enable_if<
563
    detail::is_deserialize_destination<TDestination>::value,
564
    DeserializationError>::type
565
deserializeMsgPack(TDestination&& dst, TChar* input, Args&&... args) {
444✔
566
  using namespace detail;
567
  return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
444✔
568
                                          input,
569
                                          detail::forward<Args>(args)...);
785✔
570
}
571

572
ARDUINOJSON_END_PUBLIC_NAMESPACE
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc