diff --git a/src/in.c b/src/in.c index 5120d5611..fa34849f7 100644 --- a/src/in.c +++ b/src/in.c @@ -46,6 +46,23 @@ ly_in_type(const struct ly_in *in) return in->type; } +static LY_ERR +ly_in_check_read(const struct ly_in *in, size_t count) +{ + size_t offset; + + if (!in->bounded) { + return LY_SUCCESS; + } + + offset = in->current - in->start; + if ((offset > in->length) || (count > in->length - offset)) { + return LY_EDENIED; + } + + return LY_SUCCESS; +} + LIBYANG_API_DEF LY_ERR ly_in_reset(struct ly_in *in) { @@ -78,6 +95,7 @@ ly_in_new_fd(int fd, struct ly_in **in) (*in)->current = (*in)->start = (*in)->func_start = addr; (*in)->line = 1; (*in)->length = length; + (*in)->bounded = 1; return LY_SUCCESS; } @@ -106,6 +124,7 @@ ly_in_fd(struct ly_in *in, int fd) in->current = in->start = addr; in->line = 1; in->length = length; + in->bounded = 1; } return prev_fd; @@ -179,6 +198,8 @@ ly_in_memory(struct ly_in *in, const char *str) if (str) { in->start = in->current = str; in->line = 1; + in->length = 0; + in->bounded = 0; } return data; @@ -299,12 +320,12 @@ ly_in_free(struct ly_in *in, ly_bool destroy) LIBYANG_API_DEF LY_ERR ly_in_read(struct ly_in *in, void *buf, size_t count) { + size_t read_count; + LY_CHECK_ARG_RET(NULL, in, buf, LY_EINVAL); - if (in->length && (in->length - (in->current - in->start) < count)) { - /* EOF */ - return LY_EDENIED; - } + read_count = (count && in->peeked) ? count - 1 : count; + LY_CHECK_RET(ly_in_check_read(in, read_count)); if (count && in->peeked) { /* read the peeked byte */ @@ -328,13 +349,11 @@ ly_in_peek(struct ly_in *in, uint8_t *peek) { LY_CHECK_ARG_RET(NULL, in, peek, LY_EINVAL); - if (in->length && (in->length - (in->current - in->start) < 1)) { - /* EOF */ - return LY_EDENIED; - } else if (in->peeked) { + if (in->peeked) { /* unsupported */ return LY_ENOT; } + LY_CHECK_RET(ly_in_check_read(in, 1)); memcpy(&in->peek, in->current, 1); in->current += 1; @@ -347,12 +366,12 @@ ly_in_peek(struct ly_in *in, uint8_t *peek) LIBYANG_API_DEF LY_ERR ly_in_skip(struct ly_in *in, size_t count) { + size_t skip_count; + LY_CHECK_ARG_RET(NULL, in, LY_EINVAL); - if (in->length && (in->length - (in->current - in->start) < count)) { - /* EOF */ - return LY_EDENIED; - } + skip_count = (count && in->peeked) ? count - 1 : count; + LY_CHECK_RET(ly_in_check_read(in, skip_count)); if (count && in->peeked) { /* skip the peeked byte */ diff --git a/src/in_internal.h b/src/in_internal.h index 270c05a9e..634553f79 100644 --- a/src/in_internal.h +++ b/src/in_internal.h @@ -28,7 +28,8 @@ struct ly_in { const char *current; /**< Current position in the input data */ const char *func_start; /**< Input data position when the last parser function was executed */ const char *start; /**< Input data start */ - size_t length; /**< mmap() length (if used) */ + size_t length; /**< input data length (if bounded) */ + ly_bool bounded; /**< whether @ref length limits reads from @ref start */ ly_bool peeked; /**< whether a byte was peeked */ uint8_t peek; /**< peeked byte, if any */ diff --git a/src/parser_data.h b/src/parser_data.h index 3af394ca5..5e13cdda4 100644 --- a/src/parser_data.h +++ b/src/parser_data.h @@ -266,21 +266,22 @@ LIBYANG_API_DECL LY_ERR lyd_parse_data_mem(const struct ly_ctx *ctx, const char uint32_t validate_options, struct lyd_node **tree); /** - * @brief Parse data from a memory buffer with a specified length. + * @brief Parse (and validate) input data as a YANG data tree from a bounded memory buffer. * - * This function parses the provided data buffer of a given length and returns the resulting data tree. + * Wrapper around ::lyd_parse_data() hiding work with the input handler and some obscure options. + * Unlike ::lyd_parse_data_mem(), @p data may contain NULL bytes and the parser will not read past @p data_len bytes. * - * @param[in] ctx libyang context for parsing. - * @param[in] data Pointer to the memory buffer containing the data to parse. - * @param[in] data_len Length of the memory buffer. - * @param[in] format Data format (e.g., XML, JSON, LYD_LYB). + * @param[in] ctx Context to connect with the tree being built here. + * @param[in] data The input data in the specified @p format to parse (and validate). + * @param[in] data_len Number of readable bytes in @p data. + * @param[in] format Format of the input data to be parsed. * @param[in] parse_options Options for parser, see @ref dataparseroptions. * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions. - * @param[in] ctx_node Optional context node for parsing (can be NULL). - * @param[out] tree Pointer to the resulting data tree (set on success). - * @return LY_ERR value indicating success or error reason. + * @param[out] tree Full parsed data tree, note that NULL can be a valid tree. + * @return LY_SUCCESS in case of successful parsing (and validation). + * @return LY_ERR value in case of error. Additional error information can be obtained from the context using ly_err* functions. */ -LIBYANG_API_DECL LY_ERR lyd_parse_data_mem_len(const struct ly_ctx *ctx, const char *data, size_t data_len, LYD_FORMAT format, +LIBYANG_API_DECL LY_ERR lyd_parse_data_mem_len(const struct ly_ctx *ctx, const char *data, uint32_t data_len, LYD_FORMAT format, uint32_t parse_options, uint32_t validate_options, struct lyd_node **tree); /** diff --git a/src/parser_lyb.c b/src/parser_lyb.c index 95aeaee3b..36efe30a6 100644 --- a/src/parser_lyb.c +++ b/src/parser_lyb.c @@ -149,8 +149,8 @@ lyb_read(void *buf, uint64_t count_bits, struct lylyb_parse_ctx *lybctx) return LY_SUCCESS; eof: - LOGERR(lybctx->ctx, LY_EDENIED, "Unexpected LYB read EOF."); - return LY_EDENIED; + LOGERR(lybctx->ctx, LY_EVALID, "Unexpected end of LYB data."); + return LY_EVALID; } /** @@ -210,8 +210,8 @@ lyb_read_count(uint32_t *count, struct lylyb_parse_ctx *lybctx) break; default: /* invalid */ - LOGINT(lybctx->ctx); - return LY_EINT; + LOGERR(lybctx->ctx, LY_EVALID, "Invalid LYB count prefix."); + return LY_EVALID; } /* correct byte order */ @@ -269,8 +269,8 @@ lyb_read_size(uint32_t *size, struct lylyb_parse_ctx *lybctx) break; default: /* invalid */ - LOGINT(lybctx->ctx); - return LY_EINT; + LOGERR(lybctx->ctx, LY_EVALID, "Invalid LYB size prefix."); + return LY_EVALID; } /* correct byte order */ @@ -351,7 +351,7 @@ lyb_read_value(const struct lysc_type *type, uint8_t **val, uint64_t *val_size_b *val_size_bits = fixed_size_bits; } else { /* parse value size in bits or bytes, uint32_t is enough because larger sizes will be stored as bytes */ - lyb_read_size(&lyb_size_bits, lybctx); + LY_CHECK_RET(lyb_read_size(&lyb_size_bits, lybctx)); *val_size_bits = lyb_size_bits; if (size_type == LYPLG_LYB_SIZE_VARIABLE_BYTES) { *val_size_bits *= 8; @@ -873,9 +873,15 @@ lyb_read_hashes(struct lylyb_parse_ctx *lybctx, LYB_HASH *hash, uint8_t *hash_co LY_CHECK_RET(lyb_read(&hash[j - 1], sizeof *hash * 8, lybctx)); /* correct collision ID */ - assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1))); + if (!(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)))) { + LOGERR(lybctx->ctx, LY_EVALID, "Invalid LYB schema hash collision ID."); + return LY_EVALID; + } /* preceded with zeros */ - assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1))))); + if (hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))) { + LOGERR(lybctx->ctx, LY_EVALID, "Invalid LYB schema hash prefix."); + return LY_EVALID; + } } *hash_count = i + 1; diff --git a/src/tree_data.c b/src/tree_data.c index 0567c4728..30a9ee5d5 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -220,14 +220,15 @@ lyd_parse_data(const struct ly_ctx *ctx, struct lyd_node *parent, struct ly_in * } LIBYANG_API_DEF LY_ERR -lyd_parse_data_mem_len(const struct ly_ctx *ctx, const char *data, size_t data_len, LYD_FORMAT format, +lyd_parse_data_mem_len(const struct ly_ctx *ctx, const char *data, uint32_t data_len, LYD_FORMAT format, uint32_t parse_options, uint32_t validate_options, struct lyd_node **tree) { LY_ERR ret; struct ly_in *in; LY_CHECK_RET(ly_in_new_memory(data, &in)); - in->length = data_len; // Set the length for the input + in->length = data_len; + in->bounded = 1; ret = lyd_parse_data(ctx, NULL, in, format, parse_options, validate_options, tree); diff --git a/tests/fuzz/lyd_parse_lyb.c b/tests/fuzz/lyd_parse_lyb.c index 2dd902f7f..500bbb8f3 100644 --- a/tests/fuzz/lyd_parse_lyb.c +++ b/tests/fuzz/lyd_parse_lyb.c @@ -1,9 +1,5 @@ -#define _GNU_SOURCE - -#include -#include #include -#include +#include #include "libyang.h" @@ -11,7 +7,6 @@ int LLVMFuzzerTestOneInput(uint8_t const *buf, size_t len) { struct ly_ctx *ctx = NULL; struct lyd_node *tree = NULL; - FILE *input = NULL; static bool log = false; const char *schema = "module fuzz-lyb {namespace urn:tests:fuzz-lyb;prefix fl;" @@ -31,26 +26,13 @@ int LLVMFuzzerTestOneInput(uint8_t const *buf, size_t len) goto cleanup; } - input = tmpfile(); - if (!input) { - goto cleanup; + if (len <= UINT32_MAX) { + lyd_parse_data_mem_len(ctx, (const char *)buf, (uint32_t)len, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, + &tree); } - if (len && (fwrite(buf, 1, len, input) != len)) { - goto cleanup; - } - fflush(input); - if (lseek(fileno(input), 0, SEEK_SET) == -1) { - goto cleanup; - } - - lyd_parse_data_fd(ctx, fileno(input), LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree); - cleanup: lyd_free_all(tree); - if (input) { - fclose(input); - } ly_ctx_destroy(ctx); return 0; } diff --git a/tests/utests/data/test_cbor.c b/tests/utests/data/test_cbor.c index e43dc5374..2da75c148 100644 --- a/tests/utests/data/test_cbor.c +++ b/tests/utests/data/test_cbor.c @@ -109,7 +109,7 @@ test_node(void **state) lyd_free_all(tree); assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(((struct utest_context *)*state)->ctx, buffer, - ly_out_printed(out), LYD_CBOR, LYD_PARSE_ONLY, 0, &tree)); + (uint32_t)ly_out_printed(out), LYD_CBOR, LYD_PARSE_ONLY, 0, &tree)); ly_out_free(out, NULL, 0); free(buffer); @@ -244,7 +244,7 @@ test_schema_mount(void **state) tree = NULL; assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, cbor_buffer, - ly_out_printed(out_cbor), LYD_CBOR, LYD_PARSE_STRICT | LYD_PARSE_ONLY, 0, &tree)); + (uint32_t)ly_out_printed(out_cbor), LYD_CBOR, LYD_PARSE_STRICT | LYD_PARSE_ONLY, 0, &tree)); ly_out_free(out_cbor, NULL, 0); free(cbor_buffer); @@ -280,7 +280,7 @@ test_opaque(void **state) lyd_free_all(tree); assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(((struct utest_context *)*state)->ctx, buffer, - ly_out_printed(out), LYD_CBOR, LYD_PARSE_ONLY | LYD_PARSE_OPAQ, 0, &tree)); + (uint32_t)ly_out_printed(out), LYD_CBOR, LYD_PARSE_ONLY | LYD_PARSE_OPAQ, 0, &tree)); ly_out_free(out, NULL, 0); free(buffer); diff --git a/tests/utests/data/test_lyb.c b/tests/utests/data/test_lyb.c index 7f582db76..d53746dcc 100644 --- a/tests/utests/data/test_lyb.c +++ b/tests/utests/data/test_lyb.c @@ -15,6 +15,7 @@ #include "utests.h" #include "hash_table.h" +#include "in_internal.h" #include "libyang.h" #define CHECK_PARSE_LYD(INPUT, OUT_NODE) \ @@ -28,12 +29,13 @@ check_print_parse(void **state, const char *data_xml, const struct ly_ctx *parse { struct lyd_node *tree_1, *tree_2 = NULL; char *lyb_out = NULL; + uint32_t lyb_len; LY_ERR r; CHECK_PARSE_LYD(data_xml, tree_1); - assert_int_equal(lyd_print_mem(&lyb_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); + assert_int_equal(utest_lyd_print_mem_len(&lyb_out, &lyb_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); - r = lyd_parse_data_mem(parse_ctx, lyb_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2); + r = lyd_parse_data_mem_len(parse_ctx, lyb_out, lyb_len, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2); if (expect_parse_success) { assert_int_equal(r, LY_SUCCESS); assert_non_null(tree_2); @@ -466,6 +468,7 @@ test_opaq(void **state) struct lyd_node *tree_1; struct lyd_node *tree_2; char *xml_out; /* tree_2 */ + uint32_t xml_len; LY_ERR rc; assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf", NULL, nc_feats)); @@ -475,9 +478,11 @@ test_opaq(void **state) ly_in_free(in, 0); assert_int_equal(rc, LY_SUCCESS); - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); ly_in_new_memory(xml_out, &in); + in->length = xml_len; + in->bounded = 1; rc = lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_LYB, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, &tree_2, NULL); ly_in_free(in, 0); assert_int_equal(rc, LY_SUCCESS); @@ -2536,6 +2541,7 @@ test_shrink(void **state) const char *mod, *data_xml; struct lyd_node *tree1, *tree2; char *lyb_out, *str; + uint32_t lyb_len; mod = "module mod { namespace \"urn:mod\"; prefix m;" @@ -2551,9 +2557,9 @@ test_shrink(void **state) /* non-shrinked */ data_xml = ""; CHECK_PARSE_LYD_PARAM(data_xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree1); - assert_int_equal(lyd_print_mem(&lyb_out, tree1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, lyb_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, - 0, &tree2)); + assert_int_equal(utest_lyd_print_mem_len(&lyb_out, &lyb_len, tree1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, lyb_out, lyb_len, LYD_LYB, + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree2)); assert_non_null(tree2); assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, tree2, LYD_XML, LYD_PRINT_SIBLINGS | LYD_PRINT_WD_ALL | LYD_PRINT_SHRINK)); @@ -2568,9 +2574,10 @@ test_shrink(void **state) /* shrinked */ data_xml = ""; CHECK_PARSE_LYD_PARAM(data_xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree1); - assert_int_equal(lyd_print_mem(&lyb_out, tree1, LYD_LYB, LYD_PRINT_SIBLINGS | LYD_PRINT_SHRINK), 0); - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, lyb_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, - 0, &tree2)); + assert_int_equal(utest_lyd_print_mem_len(&lyb_out, &lyb_len, tree1, LYD_LYB, + LYD_PRINT_SIBLINGS | LYD_PRINT_SHRINK), 0); + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, lyb_out, lyb_len, LYD_LYB, + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree2)); assert_null(tree2); free(lyb_out); @@ -2785,6 +2792,7 @@ test_skip_module_check(void **state) struct ly_ctx *ctx; struct ly_in *in; char *lyb_out; + uint32_t lyb_len; struct lyd_node *tree1, *tree2; const char *feats1[] = {"feat1", NULL}; const char *feats2[] = {"feat1", "feat2", NULL}; @@ -2818,14 +2826,14 @@ test_skip_module_check(void **state) CHECK_PARSE_LYD(data_xml, tree1); /* print it to LYB using UTEST_LYCTX (with mod_rev_1) */ - assert_int_equal(lyd_print_mem(&lyb_out, tree1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); + assert_int_equal(utest_lyd_print_mem_len(&lyb_out, &lyb_len, tree1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); /* parse it in the new context (with mod_rev_2) - should fail due to revision mismatch */ - assert_int_not_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, lyb_out, LYD_LYB, + assert_int_not_equal(LY_SUCCESS, lyd_parse_data_mem_len(ctx, lyb_out, lyb_len, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree2)); /* parse it in the new context (with mod_rev_2) - should succeed when skipping module check */ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, lyb_out, LYD_LYB, + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(ctx, lyb_out, lyb_len, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT | LYD_PARSE_LYB_SKIP_MODULE_CHECK, 0, &tree2)); assert_non_null(tree2); CHECK_LYD(tree1, tree2); @@ -2864,14 +2872,14 @@ test_skip_module_check(void **state) CHECK_PARSE_LYD(data_xml, tree1); /* print it to LYB using UTEST_LYCTX (with feat1) */ - assert_int_equal(lyd_print_mem(&lyb_out, tree1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); + assert_int_equal(utest_lyd_print_mem_len(&lyb_out, &lyb_len, tree1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); /* parse it in the new context (with feat1 and feat2) - should fail due to feature mismatch */ - assert_int_not_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, lyb_out, LYD_LYB, + assert_int_not_equal(LY_SUCCESS, lyd_parse_data_mem_len(ctx, lyb_out, lyb_len, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree2)); /* parse it in the new context (with feat1 and feat2) - should succeed when skipping module check */ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, lyb_out, LYD_LYB, + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(ctx, lyb_out, lyb_len, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT | LYD_PARSE_LYB_SKIP_MODULE_CHECK, 0, &tree2)); assert_non_null(tree2); CHECK_LYD(tree1, tree2); @@ -2882,6 +2890,53 @@ test_skip_module_check(void **state) ly_ctx_destroy(ctx); } +static void +test_memory_bounds(void **state) +{ + const char *mod, *data_xml; + struct lyd_node *tree, *parsed = NULL; + char *lyb; + uint32_t lyb_len; + + mod = + "module bounds {namespace urn:bounds;prefix b;" + "container cont {leaf value {type string;}}}"; + UTEST_ADD_MODULE(mod, LYS_IN_YANG, NULL, NULL); + + data_xml = "test"; + CHECK_PARSE_LYD(data_xml, tree); + assert_int_equal(LY_SUCCESS, utest_lyd_print_mem_len(&lyb, &lyb_len, tree, LYD_LYB, LYD_PRINT_SIBLINGS)); + + /* Legacy unbounded memory input remains supported. */ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, lyb, LYD_LYB, + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &parsed)); + assert_non_null(parsed); + CHECK_LYD(tree, parsed); + lyd_free_all(parsed); + parsed = NULL; + + /* Empty and truncated bounded inputs must fail without reading past their buffers. */ + assert_int_equal(LY_EVALID, lyd_parse_data_mem_len(UTEST_LYCTX, lyb, 0, LYD_LYB, + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &parsed)); + assert_null(parsed); + UTEST_LOG_CTX_CLEAN; + + assert_int_equal(LY_EVALID, lyd_parse_data_mem_len(UTEST_LYCTX, lyb, lyb_len - 1, LYD_LYB, + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &parsed)); + assert_null(parsed); + UTEST_LOG_CTX_CLEAN; + + /* The complete bounded input still parses successfully. */ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, lyb, lyb_len, LYD_LYB, + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &parsed)); + assert_non_null(parsed); + CHECK_LYD(tree, parsed); + + free(lyb); + lyd_free_all(tree); + lyd_free_all(parsed); +} + int main(void) { @@ -2899,6 +2954,7 @@ main(void) UTEST(test_bits, setup), UTEST(test_different_contexts, setup), UTEST(test_skip_module_check, setup), + UTEST(test_memory_bounds), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/tests/utests/data/test_tree_data_sorted.c b/tests/utests/data/test_tree_data_sorted.c index 9e9b9da67..1c4f31053 100644 --- a/tests/utests/data/test_tree_data_sorted.c +++ b/tests/utests/data/test_tree_data_sorted.c @@ -1106,6 +1106,7 @@ test_parse_data(void **state) { const char *schema, *data; char *lyb_out; + uint32_t lyb_len; struct lys_module *mod; struct lyd_node *tree, *tree2; @@ -1131,9 +1132,9 @@ test_parse_data(void **state) /* data tree is used in the next check */ /* lyb */ - assert_int_equal(lyd_print_mem(&lyb_out, tree, LYD_LYB, LYD_PRINT_SIBLINGS), 0); - assert_int_equal(lyd_parse_data_mem(UTEST_LYCTX, lyb_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, - 0, &tree2), LY_SUCCESS); + assert_int_equal(utest_lyd_print_mem_len(&lyb_out, &lyb_len, tree, LYD_LYB, LYD_PRINT_SIBLINGS), 0); + assert_int_equal(lyd_parse_data_mem_len(UTEST_LYCTX, lyb_out, lyb_len, LYD_LYB, + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree2), LY_SUCCESS); assert_true(tree2 && tree2->meta && tree2->next); assert_string_equal(tree2->meta->name, META_NAME); CHECK_LYD_VALUE(((struct lyd_node_term *)tree2)->value, UINT32, "1", 1); diff --git a/tests/utests/extensions/test_schema_mount.c b/tests/utests/extensions/test_schema_mount.c index 560ed50e0..58abac71f 100644 --- a/tests/utests/extensions/test_schema_mount.c +++ b/tests/utests/extensions/test_schema_mount.c @@ -472,6 +472,7 @@ test_parse_inline(void **state) { const char *xml, *json; char *lyb; + uint32_t lyb_len; struct lyd_node *data; const struct ly_ctx *ext_ctx; @@ -666,10 +667,10 @@ test_parse_inline(void **state) CHECK_LYD_STRING_PARAM(data, json, LYD_JSON, LYD_PRINT_SIBLINGS); assert_ptr_equal(ext_ctx, LYD_CTX(lyd_child_no_keys(data))); - assert_int_equal(LY_SUCCESS, lyd_print_mem(&lyb, data, LYD_LYB, 0)); + assert_int_equal(LY_SUCCESS, utest_lyd_print_mem_len(&lyb, &lyb_len, data, LYD_LYB, 0)); lyd_free_siblings(data); - CHECK_PARSE_LYD_PARAM(lyb, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_PARSE_LYD_PARAM_LEN(lyb, lyb_len, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); assert_ptr_equal(ext_ctx, LYD_CTX(lyd_child_no_keys(data))); free(lyb); lyd_free_siblings(data); @@ -680,6 +681,7 @@ test_parse_shared(void **state) { const char *xml, *json; char *lyb; + uint32_t lyb_len; struct lyd_node *data; ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, @@ -1089,10 +1091,11 @@ test_parse_shared(void **state) CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); CHECK_LYD_STRING_PARAM(data, json, LYD_JSON, LYD_PRINT_SIBLINGS); - assert_int_equal(LY_SUCCESS, lyd_print_mem(&lyb, data, LYD_LYB, LYD_PRINT_SIBLINGS)); + assert_int_equal(LY_SUCCESS, + utest_lyd_print_mem_len(&lyb, &lyb_len, data, LYD_LYB, LYD_PRINT_SIBLINGS)); lyd_free_siblings(data); - CHECK_PARSE_LYD_PARAM(lyb, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_PARSE_LYD_PARAM_LEN(lyb, lyb_len, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); free(lyb); lyd_free_siblings(data); } @@ -1420,6 +1423,7 @@ test_parse_config(void **state) { const char *xml; char *lyb; + uint32_t lyb_len; struct lyd_node *data, *key_node; const struct lyd_node *node; @@ -1509,9 +1513,9 @@ test_parse_config(void **state) node = lyd_child_no_keys(node); assert_string_equal(LYD_NAME(node), "type"); assert_true(node->schema->flags & LYS_CONFIG_R); - lyd_print_mem(&lyb, data, LYD_LYB, 0); + assert_int_equal(LY_SUCCESS, utest_lyd_print_mem_len(&lyb, &lyb_len, data, LYD_LYB, 0)); lyd_free_siblings(data); - CHECK_PARSE_LYD_PARAM(lyb, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_PARSE_LYD_PARAM_LEN(lyb, lyb_len, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); free(lyb); node = lyd_child_no_keys(data); diff --git a/tests/utests/extensions/test_structure.c b/tests/utests/extensions/test_structure.c index 230ccaf17..8e9fdf812 100644 --- a/tests/utests/extensions/test_structure.c +++ b/tests/utests/extensions/test_structure.c @@ -212,6 +212,7 @@ test_parse(void **state) struct lyd_node *tree = NULL, *node; const char *yang, *xml, *json; char *lyb; + uint32_t lyb_len; yang = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix a;" "import ietf-yang-structure-ext {prefix sx;}" @@ -249,10 +250,11 @@ test_parse(void **state) ly_out_new_memory(&lyb, 0, &UTEST_OUT); assert_int_equal(LY_SUCCESS, lyd_print_tree(UTEST_OUT, tree, LYD_LYB, 0)); + lyb_len = (uint32_t)ly_out_printed(UTEST_OUT); ly_out_free(current_utest_context->out, NULL, 0); lyd_free_all(tree); - ly_in_memory(UTEST_IN, lyb); - assert_int_equal(LY_SUCCESS, lyd_parse_data(UTEST_LYCTX, NULL, UTEST_IN, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree)); + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, lyb, lyb_len, LYD_LYB, LYD_PARSE_STRICT, + LYD_VALIDATE_PRESENT, &tree)); free(lyb); lyd_free_all(tree); @@ -281,10 +283,11 @@ test_parse(void **state) ly_out_new_memory(&lyb, 0, &UTEST_OUT); assert_int_equal(LY_SUCCESS, lyd_print_tree(UTEST_OUT, tree, LYD_LYB, 0)); + lyb_len = (uint32_t)ly_out_printed(UTEST_OUT); ly_out_free(current_utest_context->out, NULL, 0); lyd_free_all(tree); - ly_in_memory(UTEST_IN, lyb); - assert_int_equal(LY_SUCCESS, lyd_parse_data(UTEST_LYCTX, NULL, UTEST_IN, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree)); + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, lyb, lyb_len, LYD_LYB, LYD_PARSE_STRICT, + LYD_VALIDATE_PRESENT, &tree)); free(lyb); /* invalid data */ diff --git a/tests/utests/types/binary.c b/tests/utests/types/binary.c index 1846d4db3..bb618fe9a 100644 --- a/tests/utests/types/binary.c +++ b/tests/utests/types/binary.c @@ -32,10 +32,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/bits.c b/tests/utests/types/bits.c index df8f61754..cd610e6fd 100644 --- a/tests/utests/types/bits.c +++ b/tests/utests/types/bits.c @@ -66,10 +66,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/boolean.c b/tests/utests/types/boolean.c index 645de9a44..d86d45684 100644 --- a/tests/utests/types/boolean.c +++ b/tests/utests/types/boolean.c @@ -49,10 +49,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/decimal64.c b/tests/utests/types/decimal64.c index ca9bc8934..81833c409 100644 --- a/tests/utests/types/decimal64.c +++ b/tests/utests/types/decimal64.c @@ -49,10 +49,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/empty.c b/tests/utests/types/empty.c index a7953b77d..38eb56fc7 100644 --- a/tests/utests/types/empty.c +++ b/tests/utests/types/empty.c @@ -49,10 +49,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/enumeration.c b/tests/utests/types/enumeration.c index 5cc8ab9d8..89bd666c0 100644 --- a/tests/utests/types/enumeration.c +++ b/tests/utests/types/enumeration.c @@ -49,10 +49,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/identityref.c b/tests/utests/types/identityref.c index b038f96e4..a62fbd4b4 100644 --- a/tests/utests/types/identityref.c +++ b/tests/utests/types/identityref.c @@ -40,10 +40,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/inet_types.c b/tests/utests/types/inet_types.c index 4756d8635..bbe3c05e7 100644 --- a/tests/utests/types/inet_types.c +++ b/tests/utests/types/inet_types.c @@ -81,10 +81,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/instanceid.c b/tests/utests/types/instanceid.c index b3afde867..02e9b9fe5 100644 --- a/tests/utests/types/instanceid.c +++ b/tests/utests/types/instanceid.c @@ -47,13 +47,15 @@ #define LYB_CHECK_START \ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ - char *xml_out, *data; + char *xml_out, *data; \ + uint32_t xml_len; #define LYB_CHECK_END \ { \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/int8.c b/tests/utests/types/int8.c index 3fb9416fb..294e0354e 100644 --- a/tests/utests/types/int8.c +++ b/tests/utests/types/int8.c @@ -69,10 +69,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/leafref.c b/tests/utests/types/leafref.c index 7469df5c7..1fe9fe08c 100644 --- a/tests/utests/types/leafref.c +++ b/tests/utests/types/leafref.c @@ -49,11 +49,13 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME1 " xmlns=\"urn:tests:" MOD_NAME "\">" DATA1 "" \ "<" NODE_NAME2 " xmlns=\"urn:tests:" MOD_NAME "\">" DATA2 ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/string.c b/tests/utests/types/string.c index 198511b05..50c0199b9 100644 --- a/tests/utests/types/string.c +++ b/tests/utests/types/string.c @@ -65,10 +65,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c index 54306e3ae..890363e19 100644 --- a/tests/utests/types/union.c +++ b/tests/utests/types/union.c @@ -49,10 +49,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ @@ -192,6 +194,7 @@ test_validation(void **state) const char *schema, *data; struct lyd_node *tree; char *out; + uint32_t out_len; schema = MODULE_CREATE_YANG("val", "leaf l1 {\n" @@ -216,9 +219,10 @@ test_validation(void **state) /* parse from LYB */ data = "auto1515"; CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); - assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_SIBLINGS)); + assert_int_equal(LY_SUCCESS, + utest_lyd_print_mem_len(&out, &out_len, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_SIBLINGS)); lyd_free_all(tree); - CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + CHECK_PARSE_LYD_PARAM_LEN(out, out_len, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); free(out); /* validate */ @@ -273,18 +277,20 @@ test_validation(void **state) /* parse from LYB #1 */ data = "2test2"; CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); - assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_SIBLINGS)); + assert_int_equal(LY_SUCCESS, + utest_lyd_print_mem_len(&out, &out_len, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_SIBLINGS)); lyd_free_all(tree); - CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + CHECK_PARSE_LYD_PARAM_LEN(out, out_len, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); free(out); lyd_free_all(tree); /* parse from LYB #2 */ data = "onetestone"; CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); - assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_SIBLINGS)); + assert_int_equal(LY_SUCCESS, + utest_lyd_print_mem_len(&out, &out_len, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_SIBLINGS)); lyd_free_all(tree); - CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + CHECK_PARSE_LYD_PARAM_LEN(out, out_len, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); free(out); /* remove the target and create another, which is represented the same way in LYB */ diff --git a/tests/utests/types/yang_types.c b/tests/utests/types/yang_types.c index 9b726cd1c..86206f47a 100644 --- a/tests/utests/types/yang_types.c +++ b/tests/utests/types/yang_types.c @@ -64,10 +64,12 @@ struct lyd_node *tree_1; \ struct lyd_node *tree_2; \ char *xml_out, *data; \ + uint32_t xml_len; \ data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA ""; \ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ - assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_int_equal(utest_lyd_print_mem_len(&xml_out, &xml_len, tree_1, LYD_LYB, LYD_PRINT_SIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem_len(UTEST_LYCTX, xml_out, xml_len, LYD_LYB, \ + LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ assert_non_null(tree_2); \ CHECK_LYD(tree_1, tree_2); \ free(xml_out); \ diff --git a/tests/utests/utests.h b/tests/utests/utests.h index 57ec519a0..a2dad5d20 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -141,6 +141,55 @@ struct utest_context { } \ } +/** + * @brief Parse (and validate) bounded data from memory as a YANG data tree. + */ +#define CHECK_PARSE_LYD_PARAM_LEN(INPUT, INPUT_LEN, INPUT_FORMAT, PARSE_OPTIONS, VALIDATE_OPTIONS, RET, OUT_NODE) \ + { \ + LY_ERR _r = lyd_parse_data_mem_len(_UC->ctx, INPUT, INPUT_LEN, INPUT_FORMAT, PARSE_OPTIONS, VALIDATE_OPTIONS, \ + &OUT_NODE); \ + if (_r != RET) { \ + if (_r) { \ + fail_msg("%s != 0x%d; MSG: %s", #RET, _r, ly_err_last(_UC->ctx)->msg); \ + } else { \ + fail_msg("%s != 0x%d", #RET, _r); \ + } \ + } \ + } + +/** + * @brief Print data into memory and return the exact binary-safe output length. + */ +static inline LY_ERR +utest_lyd_print_mem_len(char **strp, uint32_t *len, const struct lyd_node *root, LYD_FORMAT format, uint32_t options) +{ + LY_ERR ret; + struct ly_out *out; + size_t printed; + + *strp = NULL; + *len = 0; + ret = ly_out_new_memory(strp, 0, &out); + if (ret) { + return ret; + } + + if (options & LYD_PRINT_SIBLINGS) { + ret = lyd_print_all(out, root, format, options & ~LYD_PRINT_SIBLINGS); + } else { + ret = lyd_print_tree(out, root, format, options); + } + + printed = ly_out_printed(out); + ly_out_free(out, NULL, 0); + if (!ret && (printed > UINT32_MAX)) { + ret = LY_EINVAL; + } else if (!ret) { + *len = (uint32_t)printed; + } + return ret; +} + /** * @brief Check if lyd_node and his subnodes have correct values. Print lyd_node and his subnodes into a string in json or xml format. * @param[in] NODE pointer to lyd_node