Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkg/nanocbor: fix decoding of indefinite arrays and maps #15411

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/nanocbor/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PKG_NAME = nanocbor
PKG_URL = https://github.com/bergzand/nanocbor
PKG_VERSION = 3a672f79b2458a96393447e50a41174f741eadc5
PKG_VERSION = 16e5a838b97fc3c912b8f419497e3fff2210994e
PKG_LICENSE = LGPL-2.1

include $(RIOTBASE)/pkg/pkg.mk
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
From 8f7e2123998b5444128ea907aaba0d847c502cde Mon Sep 17 00:00:00 2001
From: Nishchay-sopho <[email protected]>
Date: Tue, 18 Aug 2020 14:34:55 +0200
Subject: [PATCH] decoder: fix decoding of indefinite arrays and maps

---
src/decoder.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/decoder.c b/src/decoder.c
index 244a6b1..9cd27b8 100644
--- a/src/decoder.c
+++ b/src/decoder.c
@@ -76,9 +76,9 @@ bool nanocbor_at_end(const nanocbor_value_t *it)
if (_over_end(it) || /* Number of items exhausted */
/* Indefinite container and the current item is the end marker */
((nanocbor_container_indefinite(it) &&
- *it->cur == (NANOCBOR_TYPE_FLOAT | NANOCBOR_SIZE_INDEFINITE))) ||
+ *it->cur == (NANOCBOR_TYPE_FLOAT << NANOCBOR_TYPE_OFFSET | NANOCBOR_VALUE_MASK))) ||
/* Or the remaining number of items is zero */
- (nanocbor_in_container(it) && it->remaining == 0)
+ (!nanocbor_container_indefinite(it) && nanocbor_in_container(it) && it->remaining == 0)
) {
end = true;
}
@@ -279,7 +279,7 @@ int _enter_container(nanocbor_value_t *it, nanocbor_value_t *container,
container->end = it->end;
container->remaining = 0;

- if (_value_match_exact(it, type | NANOCBOR_VALUE_MASK) == 1) {
+ if (_value_match_exact(it, (((unsigned)type << NANOCBOR_TYPE_OFFSET) | NANOCBOR_SIZE_INDEFINITE)) == 1) {
container->flags = NANOCBOR_DECODER_FLAG_INDEFINITE |
NANOCBOR_DECODER_FLAG_CONTAINER;
container->cur = it->cur;
--
2.25.1

133 changes: 133 additions & 0 deletions tests/pkg_nanocbor/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,143 @@ void test_nanocbor_encode(void)
TEST_ASSERT_EQUAL_INT(0, memcmp(buf, expected, sizeof(expected)));
}

enum {
CFG_FOO,
CFG_BAR,
CFG_RANGE,
};

typedef struct {
uint32_t foo;
uint32_t bar;
uint32_t min;
uint32_t mean;
uint32_t max;
} test_cfg_t;

static size_t _serialize_config(uint8_t *buffer, size_t len, const test_cfg_t *cfg)
{
nanocbor_encoder_t enc;
nanocbor_encoder_init(&enc, buffer, len);

nanocbor_fmt_map_indefinite(&enc);

/* write key - value pair*/
nanocbor_fmt_uint(&enc, CFG_FOO);
nanocbor_fmt_uint(&enc, cfg->foo);

/* write key - value pair*/
nanocbor_fmt_uint(&enc, CFG_BAR);
nanocbor_fmt_uint(&enc, cfg->bar);

/* write key - value pair*/
nanocbor_fmt_uint(&enc, CFG_RANGE);
nanocbor_fmt_array(&enc, 3);
nanocbor_fmt_uint(&enc, cfg->min);
nanocbor_fmt_uint(&enc, cfg->mean);
nanocbor_fmt_uint(&enc, cfg->max);

nanocbor_fmt_end_indefinite(&enc);

return nanocbor_encoded_len(&enc);
}

static bool _decode_period(nanocbor_value_t *it, test_cfg_t *cfg)
{
nanocbor_value_t array;

if (nanocbor_enter_array(it, &array) <= 0) {
return false;
}

if (nanocbor_get_uint32(&array, &cfg->min) <= 0) {
return false;
}

if (nanocbor_get_uint32(&array, &cfg->mean) <= 0) {
return false;
}

if (nanocbor_get_uint32(&array, &cfg->max) <= 0) {
return false;
}

nanocbor_leave_container(it, &array);

return true;
}

static bool _cfg_cb(nanocbor_value_t *map, uint32_t key, void *dst)
{
test_cfg_t *cfg = dst;

switch (key) {
case CFG_FOO:
return nanocbor_get_uint32(map, &cfg->foo) > 0;
case CFG_BAR:
return nanocbor_get_uint32(map, &cfg->bar) > 0;
case CFG_RANGE:
return _decode_period(map, cfg);
default:
nanocbor_skip(map);
}

return true;
}

static bool _parse_config(const uint8_t *buffer, size_t len, test_cfg_t *cfg)
{
nanocbor_value_t msg, map;
nanocbor_decoder_init(&msg, buffer, len);

if (nanocbor_enter_map(&msg, &map) < 0) {
return false;
}

while (!nanocbor_at_end(&map)) {
uint32_t key;
if (nanocbor_get_uint32(&map, &key) < 0) {
return false;
}

if (!_cfg_cb(&map, key, cfg)) {
return false;
}
}

return true;
}

void test_nanocbor_encode_decode_cfg(void)
{
uint8_t buffer[64];

test_cfg_t cfg = {
.foo = 23,
.bar = 42,
.min = 5,
.mean = 30,
.max = 60,
};

size_t len = _serialize_config(buffer, sizeof(buffer), &cfg);
TEST_ASSERT(len < sizeof(buffer));

test_cfg_t new_cfg;
TEST_ASSERT(_parse_config(buffer, len, &new_cfg));

TEST_ASSERT_EQUAL_INT(cfg.foo, new_cfg.foo);
TEST_ASSERT_EQUAL_INT(cfg.bar, new_cfg.bar);
TEST_ASSERT_EQUAL_INT(cfg.min, new_cfg.min);
TEST_ASSERT_EQUAL_INT(cfg.mean, new_cfg.mean);
TEST_ASSERT_EQUAL_INT(cfg.max, new_cfg.max);
}

Test *tests_nanocbor(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(test_nanocbor_encode),
new_TestFixture(test_nanocbor_encode_decode_cfg),
};
EMB_UNIT_TESTCALLER(nanocbor_tests, NULL, NULL, fixtures);
return (Test *)&nanocbor_tests;
Expand Down