From 9cc00b7a8de5170742f88a1320ff068dce08584b Mon Sep 17 00:00:00 2001 From: Affan Ziya Date: Mon, 26 Oct 2026 21:06:02 +0530 Subject: [PATCH] parser cbor BUGFIX check characters of text strings lydcbor_item_to_string() copied CBOR strings verbatim while terms are created with is_utf8 set, so the string plugin skipped its character check. Values with NUL bytes, control characters or invalid UTF-8 were accepted, and a value with an embedded NUL is inserted into the dictionary with its full length but removed by strlen(), dropping a reference of a different record. --- src/parser_cbor.c | 26 ++++++++++++++++++++++++++ tests/utests/data/test_cbor.c | 6 ++++++ 2 files changed, 32 insertions(+) diff --git a/src/parser_cbor.c b/src/parser_cbor.c index 29abdbd17..ccad30fb3 100644 --- a/src/parser_cbor.c +++ b/src/parser_cbor.c @@ -349,6 +349,30 @@ lydcbor_value_type_hint(struct lyd_cbor_ctx *lydctx, const cbor_item_t *item, ui return LY_SUCCESS; } +/** + * @brief Check that a CBOR string contains only valid YANG string characters. + * + * @param[in] str String to check. + * @param[in] str_len Length of @p str. + * @return LY_ERR value. + */ +static LY_ERR +lydcbor_check_string(const char *str, size_t str_len) +{ + size_t parsed = 0; + uint32_t len; + + while (parsed < str_len) { + if (ly_checkutf8(str + parsed, str_len - parsed, &len)) { + LOGVAL(NULL, NULL, LY_VCODE_INCHAR, str[parsed]); + return LY_EVALID; + } + parsed += len; + } + + return LY_SUCCESS; +} + /** * @brief Convert a CBOR item to a string representation. * @@ -399,6 +423,7 @@ lydcbor_item_to_string(const cbor_item_t *item, char **str_val, size_t *str_len) LY_CHECK_ERR_RET(!*str_val, LOGMEM(NULL), LY_EMEM); memcpy(*str_val, cbor_bytestring_handle(item), *str_len); (*str_val)[*str_len] = '\0'; + LY_CHECK_ERR_RET(lydcbor_check_string(*str_val, *str_len), free(*str_val); *str_val = NULL, LY_EVALID); break; case CBOR_TYPE_STRING: *str_len = cbor_string_length(item); @@ -406,6 +431,7 @@ lydcbor_item_to_string(const cbor_item_t *item, char **str_val, size_t *str_len) LY_CHECK_ERR_RET(!*str_val, LOGMEM(NULL), LY_EMEM); memcpy(*str_val, cbor_string_handle(item), *str_len); (*str_val)[*str_len] = '\0'; + LY_CHECK_ERR_RET(lydcbor_check_string(*str_val, *str_len), free(*str_val); *str_val = NULL, LY_EVALID); break; case CBOR_TYPE_FLOAT_CTRL: if (cbor_float_ctrl_is_ctrl(item)) { diff --git a/tests/utests/data/test_cbor.c b/tests/utests/data/test_cbor.c index fab33ad4c..6cbf322a8 100644 --- a/tests/utests/data/test_cbor.c +++ b/tests/utests/data/test_cbor.c @@ -404,6 +404,12 @@ test_invalid_input(void **state) CHECK_PARSE_LYD_PARAM_LEN("\xa1", 1, LYD_CBOR, 0, 0, LY_EVALID, tree); CHECK_LOG_CTX("Failed to parse CBOR data (not enough data).", NULL, 1); + /* text strings must be checked for invalid characters like in JSON and XML */ + CHECK_PARSE_LYD_PARAM_LEN("\xa1\x70" "cbor-test:lf-str" "\x65" "ab\0cd", 24, LYD_CBOR, LYD_PARSE_ONLY, 0, + LY_EVALID, tree); + CHECK_PARSE_LYD_PARAM_LEN("\xa1\x70" "cbor-test:lf-str" "\x62" "a\xff", 21, LYD_CBOR, LYD_PARSE_ONLY, 0, + LY_EVALID, tree); + assert_int_equal(LY_EVALID, lyd_new_path(NULL, UTEST_LYCTX, "/cbor-test:lf-intg8", "1000", 0, &tree)); CHECK_LOG_CTX("Value \"1000\" is out of type int8 min/max bounds.", "/cbor-test:lf-intg8", 0); }