diff --git a/sys/net/application_layer/unicoap/options.c b/sys/net/application_layer/unicoap/options.c index f9bcd6bc6971..028ea1c0a7bf 100644 --- a/sys/net/application_layer/unicoap/options.c +++ b/sys/net/application_layer/unicoap/options.c @@ -546,6 +546,11 @@ ssize_t unicoap_options_copy_value(const unicoap_options_t* options, unicoap_opt if (size < 0) { return size; } + if (size == 0) { + /* value 0 SHOULD have been encoded as zero-length value, see RFC7252, Section 3.2 */ + *dest = 0; + return size; + } if ((size_t)size > capacity) { return -ENOBUFS; } @@ -923,6 +928,11 @@ ssize_t _unicoap_options_get_variable_uint(const unicoap_options_t* options, if (size < 0) { return size; } + if (size == 0) { + /* value 0 SHOULD have been encoded as zero-length value, see RFC7252, Section 3.2 */ + *uint = 0; + return size; + } if ((size_t)size > max_size) { return -EBADOPT; } diff --git a/tests/unittests/tests-unicoap/tests-unicoap-options.c b/tests/unittests/tests-unicoap/tests-unicoap-options.c index 495be248d88e..e9735a4cf04d 100644 --- a/tests/unittests/tests-unicoap/tests-unicoap-options.c +++ b/tests/unittests/tests-unicoap/tests-unicoap-options.c @@ -383,6 +383,27 @@ static void test_remove_multiple(void) _TEST_ASSERT_EQUAL_BYTES(options_blob, unicoap_options_data(&options), sizeof(options_blob)); } +static void test_option_value_uses_shortest_possible_representation(void) +{ + static const uint8_t options_blob[] = { 0x00 }; + const unicoap_option_number_t OPTION_NUMBER = 0; // RESERVED + const uint32_t OPTION_VALUE = 0; + UNICOAP_OPTIONS_ALLOC_STATIC(options, 10); + TEST_ASSERT_EQUAL_INT(0, unicoap_options_add_uint(&options, OPTION_NUMBER, OPTION_VALUE)); + TEST_ASSERT_EQUAL_INT(sizeof(options_blob), unicoap_options_size(&options)); + _TEST_ASSERT_EQUAL_BYTES(options_blob, unicoap_options_data(&options), sizeof(options_blob)); + + uint8_t uint8_val = 42; + TEST_ASSERT_EQUAL_INT(0, unicoap_options_get_uint8(&options, OPTION_NUMBER, &uint8_val)); + TEST_ASSERT_EQUAL_INT(OPTION_VALUE, uint8_val); + uint16_t uint16_val = 42; + TEST_ASSERT_EQUAL_INT(0, unicoap_options_get_uint16(&options, OPTION_NUMBER, &uint16_val)); + TEST_ASSERT_EQUAL_INT(OPTION_VALUE, uint16_val); + uint32_t uint32_val = 42; + TEST_ASSERT_EQUAL_INT(0, unicoap_options_get_uint32(&options, OPTION_NUMBER, &uint32_val)); + TEST_ASSERT_EQUAL_INT(OPTION_VALUE, uint32_val); +} + Test* tests_unicoap_options(void) { EMB_UNIT_TESTFIXTURES(fixtures){ @@ -393,6 +414,7 @@ Test* tests_unicoap_options(void) new_TestFixture(test_remove_leading), new_TestFixture(test_remove_trailing), new_TestFixture(test_remove_multiple), + new_TestFixture(test_option_value_uses_shortest_possible_representation), }; EMB_UNIT_TESTCALLER(test_unicoap, NULL, NULL, fixtures);