From 2b69bd2c2d8beaa09ae798374181ae5c0e6fe79a Mon Sep 17 00:00:00 2001 From: aravindor Date: Fri, 13 Nov 2026 22:35:10 +0530 Subject: [PATCH] schema diff, types, parsers REFACTOR bound the remaining string writes The schema diff tree, the decimal64 / ipv4-prefix / ipv6-prefix canonical value printers, the date/time helpers and lysc_path_until() still built strings with sprintf()/strcpy() into buffers sized by hand. Each buffer is already large enough, but the writes were unbounded. Convert them to snprintf() bounded by the buffer (sizeof or the allocation size). Output is unchanged. The YANG and YIN pattern modifier parsers duplicated the pattern with malloc() + strcpy(), use strdup() there. The YIN revision-date parser copies LY_REV_SIZE bytes, the length lys_check_date() has just verified. --- src/parser_yang.c | 5 ++- src/parser_yin.c | 5 +-- src/plugins_types/decimal64.c | 6 +-- src/plugins_types/ipv4_address_prefix.c | 2 +- src/plugins_types/ipv6_address_prefix.c | 2 +- src/schema_diff_tree.c | 60 ++++++++++++------------- src/tree_data_common.c | 4 +- src/tree_schema.c | 2 +- 8 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/parser_yang.c b/src/parser_yang.c index df9982906..d53431b29 100644 --- a/src/parser_yang.c +++ b/src/parser_yang.c @@ -11,6 +11,8 @@ * * https://opensource.org/licenses/BSD-3-Clause */ +#define _GNU_SOURCE /* strdup */ + #include "parser_internal.h" #include @@ -2206,9 +2208,8 @@ parse_type_pattern_modifier(struct lysp_yang_ctx *ctx, struct lysp_restr *restr) } /* replace the value in the dictionary */ - buf = malloc(strlen(restr->arg.str) + 1); + buf = strdup(restr->arg.str); LY_CHECK_ERR_GOTO(!buf, LOGMEM(PARSER_CTX(ctx)); ret = LY_EMEM, cleanup); - strcpy(buf, restr->arg.str); lysdict_remove(PARSER_CTX(ctx), restr->arg.str); assert(buf[0] == LYSP_RESTR_PATTERN_ACK); diff --git a/src/parser_yin.c b/src/parser_yin.c index cf8890502..12f1046ea 100644 --- a/src/parser_yin.c +++ b/src/parser_yin.c @@ -1005,9 +1005,8 @@ yin_parse_modifier(struct lysp_yin_ctx *ctx, const void *parent, const char **pa lysdict_remove(ctx->xmlctx->ctx, temp_val); /* allocate new value */ - modified_val = malloc(strlen(*pat) + 1); + modified_val = strdup(*pat); LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM); - strcpy(modified_val, *pat); lysdict_remove(ctx->xmlctx->ctx, *pat); /* modify the new value */ @@ -1994,7 +1993,7 @@ yin_parse_revision_date(struct lysp_yin_ctx *ctx, char *rev, struct lysp_ext_ins LY_CHECK_ERR_RET(lys_check_date(PARSER_CTX(ctx), temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS, lysdict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID); - strcpy(rev, temp_rev); + memcpy(rev, temp_rev, LY_REV_SIZE); lysdict_remove(ctx->xmlctx->ctx, temp_rev); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), rev, LY_STMT_REVISION_DATE, NULL, exts)); diff --git a/src/plugins_types/decimal64.c b/src/plugins_types/decimal64.c index a678abfc8..bc5168535 100644 --- a/src/plugins_types/decimal64.c +++ b/src/plugins_types/decimal64.c @@ -53,14 +53,14 @@ decimal64_num2str(int64_t num, struct lysc_type_dec *type, char **str) LY_CHECK_RET(!ret, LY_EMEM); if (num) { - int count = sprintf(ret, "%" PRId64 " ", num); + int count = snprintf(ret, LY_NUMBER_MAXLEN, "%" PRId64 " ", num); if (((num > 0) && ((count - 1) <= type->fraction_digits)) || ((count - 2) <= type->fraction_digits)) { /* we have 0. value, print the value with the leading zeros * (one for 0. and also keep the correct with of num according * to fraction-digits value) * for (num < 0) - extra character for '-' sign */ - count = sprintf(ret, "%0*" PRId64 " ", (num > 0) ? (type->fraction_digits + 1) : (type->fraction_digits + 2), num); + count = snprintf(ret, LY_NUMBER_MAXLEN, "%0*" PRId64 " ", (num > 0) ? (type->fraction_digits + 1) : (type->fraction_digits + 2), num); } for (uint8_t i = type->fraction_digits, j = 1; i > 0; i--) { if (j && (i > 1) && (ret[count - 2] == '0')) { @@ -75,7 +75,7 @@ decimal64_num2str(int64_t num, struct lysc_type_dec *type, char **str) ret[count - 1] = '.'; } else { /* zero */ - sprintf(ret, "0.0"); + snprintf(ret, LY_NUMBER_MAXLEN, "0.0"); } *str = ret; diff --git a/src/plugins_types/ipv4_address_prefix.c b/src/plugins_types/ipv4_address_prefix.c index 350b1a3ae..150e867ac 100644 --- a/src/plugins_types/ipv4_address_prefix.c +++ b/src/plugins_types/ipv4_address_prefix.c @@ -275,7 +275,7 @@ lyplg_type_print_ipv4_address_prefix(const struct ly_ctx *ctx, const struct lyd_ } /* add the prefix */ - sprintf(ret + strlen(ret), "/%" PRIu8, val->prefix); + snprintf(ret + strlen(ret), INET_ADDRSTRLEN + 4 - strlen(ret), "/%" PRIu8, val->prefix); /* store it */ if (lydict_insert_zc(ctx, ret, (const char **)&value->_canonical)) { diff --git a/src/plugins_types/ipv6_address_prefix.c b/src/plugins_types/ipv6_address_prefix.c index bf9f828f9..2bdcce8a2 100644 --- a/src/plugins_types/ipv6_address_prefix.c +++ b/src/plugins_types/ipv6_address_prefix.c @@ -289,7 +289,7 @@ lyplg_type_print_ipv6_address_prefix(const struct ly_ctx *ctx, const struct lyd_ } /* add the prefix */ - sprintf(ret + strlen(ret), "/%" PRIu8, val->prefix); + snprintf(ret + strlen(ret), INET6_ADDRSTRLEN + 4 - strlen(ret), "/%" PRIu8, val->prefix); /* store it */ if (lydict_insert_zc(ctx, ret, (const char **)&value->_canonical)) { diff --git a/src/schema_diff_tree.c b/src/schema_diff_tree.c index 82cce7b69..3c0089d6d 100644 --- a/src/schema_diff_tree.c +++ b/src/schema_diff_tree.c @@ -316,7 +316,7 @@ schema_diff_pnode_path(const struct lysp_node *node) path = ly_realloc(path, new_len + 1); LY_CHECK_ERR_GOTO(!path, LOGMEM(NULL), cleanup); - sprintf(path + path_len, "/%s%s%s", node_pre ? node_pre : "", nodes[i]->name, node_post ? node_post : ""); + snprintf(path + path_len, new_len + 1 - path_len, "/%s%s%s", node_pre ? node_pre : "", nodes[i]->name, node_post ? node_post : ""); path_len = new_len; } while (i); @@ -491,11 +491,11 @@ schema_diff_ext_inst_substmts_bitenums(const struct ly_ctx *ctx, const struct ly /* value/position */ if (items[u].flags & LYS_IS_ENUM) { - sprintf(num_str, "%" PRId32, items[u].value); + snprintf(num_str, sizeof num_str, "%" PRId32, items[u].value); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, "value", num_str, &bitenum_node->child), cleanup); } else { - sprintf(num_str, "%" PRIu32, items[u].position); + snprintf(num_str, sizeof num_str, "%" PRIu32, items[u].position); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, "position", num_str, &bitenum_node->child), cleanup); } @@ -611,16 +611,16 @@ schema_diff_range2str(struct lysc_range_part *parts, ly_bool is_signed, char **s LYA_FOR(parts, u) { if (is_signed) { - sprintf(num_min_str, "%" PRId64, parts[u].min_64); + snprintf(num_min_str, sizeof num_min_str, "%" PRId64, parts[u].min_64); if (parts[u].min_64 < parts[u].max_64) { - sprintf(num_max_str, "%" PRId64, parts[u].max_64); + snprintf(num_max_str, sizeof num_max_str, "%" PRId64, parts[u].max_64); } else { num_max_str[0] = '\0'; } } else { - sprintf(num_min_str, "%" PRIu64, parts[u].min_u64); + snprintf(num_min_str, sizeof num_min_str, "%" PRIu64, parts[u].min_u64); if (parts[u].min_u64 < parts[u].max_u64) { - sprintf(num_max_str, "%" PRIu64, parts[u].max_u64); + snprintf(num_max_str, sizeof num_max_str, "%" PRIu64, parts[u].max_u64); } else { num_max_str[0] = '\0'; } @@ -630,7 +630,7 @@ schema_diff_range2str(struct lysc_range_part *parts, ly_bool is_signed, char **s s = ly_realloc(s, new_len + 1); LY_CHECK_ERR_GOTO(!s, LOGMEM(NULL); rc = LY_EMEM, cleanup); - sprintf(s + s_len, "%s%s%s%s", s_len ? "|" : "", num_min_str, num_max_str[0] ? ".." : "", + snprintf(s + s_len, new_len + 1 - s_len, "%s%s%s%s", s_len ? "|" : "", num_min_str, num_max_str[0] ? ".." : "", num_max_str[0] ? num_max_str : ""); s_len = new_len; } @@ -877,7 +877,7 @@ schema_diff_ext_inst_substmts_type(const struct ly_ctx *ctx, const struct lysc_t type_dec = (const struct lysc_type_dec *)type; /* fraction-digits */ - sprintf(num_str, "%" PRIu8, type_dec->fraction_digits); + snprintf(num_str, sizeof num_str, "%" PRIu8, type_dec->fraction_digits); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, "fraction-digits", num_str, child_p), cleanup); /* range */ @@ -1099,12 +1099,12 @@ schema_diff_ext_inst_substmts_nodes_r(const struct lysc_node *sibling, struct ly max = llist->max; } if (min > 0) { - sprintf(num_str, "%" PRIu32, min); + snprintf(num_str, sizeof num_str, "%" PRIu32, min); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, "min-elements", num_str, &node->child), cleanup); } if (max < UINT32_MAX) { - sprintf(num_str, "%" PRIu32, max); + snprintf(num_str, sizeof num_str, "%" PRIu32, max); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, "max-elements", num_str, &node->child), cleanup); } @@ -1221,7 +1221,7 @@ schema_diff_ext_inst_substmts(const struct ly_ctx *ctx, const struct lysc_ext_su /* uint8 number */ if (*(substmts[u].storage_p)) { - sprintf(num_str, "%" PRIu8, *(uint8_t *)substmts[u].storage_p); + snprintf(num_str, sizeof num_str, "%" PRIu8, *(uint8_t *)substmts[u].storage_p); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, lys_stmt_str(substmts[u].stmt), num_str, child_p), cleanup); } @@ -1253,7 +1253,7 @@ schema_diff_ext_inst_substmts(const struct ly_ctx *ctx, const struct lysc_ext_su /* uint32 number */ if (*(uint32_t *)substmts[u].storage_p < UINT32_MAX) { - sprintf(num_str, "%" PRIu32, *(uint32_t *)substmts[u].storage_p); + snprintf(num_str, sizeof num_str, "%" PRIu32, *(uint32_t *)substmts[u].storage_p); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, "max-elements", num_str, child_p), cleanup); } @@ -1264,7 +1264,7 @@ schema_diff_ext_inst_substmts(const struct ly_ctx *ctx, const struct lysc_ext_su /* uint32 number */ if (*(uint32_t *)substmts[u].storage_p > 0) { - sprintf(num_str, "%" PRIu32, *(uint32_t *)substmts[u].storage_p); + snprintf(num_str, sizeof num_str, "%" PRIu32, *(uint32_t *)substmts[u].storage_p); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, "min-elements", num_str, child_p), cleanup); } @@ -1290,7 +1290,7 @@ schema_diff_ext_inst_substmts(const struct ly_ctx *ctx, const struct lysc_ext_su char num_str[21]; /* uint64 number */ - sprintf(num_str, "%" PRIu64, *(uint64_t *)substmts[u].storage_p); + snprintf(num_str, sizeof num_str, "%" PRIu64, *(uint64_t *)substmts[u].storage_p); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, "position", num_str, child_p), cleanup); break; } @@ -1334,7 +1334,7 @@ schema_diff_ext_inst_substmts(const struct ly_ctx *ctx, const struct lysc_ext_su char num_str[21]; /* int64 number */ - sprintf(num_str, "%" PRId64, *(int64_t *)substmts[u].storage_p); + snprintf(num_str, sizeof num_str, "%" PRId64, *(int64_t *)substmts[u].storage_p); LY_CHECK_GOTO(rc = schema_diff_ext_inst_substmts_child_add(ctx, "value", num_str, child_p), cleanup); break; } @@ -1958,11 +1958,11 @@ schema_diff_parsed_enum(const struct lysp_type_enum *enm, ly_bool is_bit, struct if (is_bit) { /* position */ - sprintf(str, "%" PRIu64, (uint64_t)enm->value); + snprintf(str, sizeof str, "%" PRIu64, (uint64_t)enm->value); LY_CHECK_GOTO(rc = lyd_new_term(enum_list, NULL, "position", str, LYD_NEW_VAL_CANON, NULL), cleanup); } else { /* value */ - sprintf(str, "%" PRId64, enm->value); + snprintf(str, sizeof str, "%" PRId64, enm->value); LY_CHECK_GOTO(rc = lyd_new_term(enum_list, NULL, "value", str, LYD_NEW_VAL_CANON, NULL), cleanup); } @@ -2011,7 +2011,7 @@ schema_diff_parsed_type(const struct lysp_type *type, struct lyd_node *cont) /* fraction-digits */ if (type->flags & LYS_SET_FRDIGITS) { - sprintf(str, "%" PRIu8, type->fraction_digits); + snprintf(str, sizeof str, "%" PRIu8, type->fraction_digits); LY_CHECK_GOTO(rc = lyd_new_term(cont, NULL, "fraction-digits", str, LYD_NEW_VAL_CANON, NULL), cleanup); } @@ -2264,7 +2264,7 @@ schema_diff_pnode(const struct lysp_node *pnode, struct lyd_node *change_cont) /* min-elements */ if (min_set) { - sprintf(buf, "%" PRIu32, min); + snprintf(buf, sizeof buf, "%" PRIu32, min); if ((rc = lyd_new_term(change_cont, NULL, "min-elements", buf, 0, NULL))) { goto cleanup; } @@ -2272,7 +2272,7 @@ schema_diff_pnode(const struct lysp_node *pnode, struct lyd_node *change_cont) /* max-elements */ if (max_set) { - sprintf(buf, "%" PRIu32, max); + snprintf(buf, sizeof buf, "%" PRIu32, max); if ((rc = lyd_new_term(change_cont, NULL, "max-elements", buf, 0, NULL))) { goto cleanup; } @@ -2405,7 +2405,7 @@ schema_diff_refine(const struct lysp_refine *refine, struct lyd_node *change_con /* min-elements */ if (refine->flags & LYS_SET_MIN) { - sprintf(buf, "%" PRIu32, refine->min); + snprintf(buf, sizeof buf, "%" PRIu32, refine->min); if ((rc = lyd_new_term(change_cont, NULL, "min-elements", buf, 0, NULL))) { goto cleanup; } @@ -2413,7 +2413,7 @@ schema_diff_refine(const struct lysp_refine *refine, struct lyd_node *change_con /* max-elements */ if (refine->flags & LYS_SET_MAX) { - sprintf(buf, "%" PRIu32, refine->max); + snprintf(buf, sizeof buf, "%" PRIu32, refine->max); if ((rc = lyd_new_term(change_cont, NULL, "max-elements", buf, 0, NULL))) { goto cleanup; } @@ -3122,7 +3122,7 @@ schema_diff_deviation(const struct lysp_deviation *dev, struct lyd_node *change_ /* min-elements */ if (flags & LYS_SET_MIN) { - sprintf(buf, "%" PRIu32, min); + snprintf(buf, sizeof buf, "%" PRIu32, min); if ((rc = lyd_new_term(dev_list, NULL, "min-elements", buf, 0, NULL))) { goto cleanup; } @@ -3130,7 +3130,7 @@ schema_diff_deviation(const struct lysp_deviation *dev, struct lyd_node *change_ /* max-elements */ if (flags & LYS_SET_MAX) { - sprintf(buf, "%" PRIu32, max); + snprintf(buf, sizeof buf, "%" PRIu32, max); if ((rc = lyd_new_term(dev_list, NULL, "max-elements", buf, 0, NULL))) { goto cleanup; } @@ -3523,10 +3523,10 @@ schema_diff_node_type_bitenums(const struct lysc_type_bitenum_item *items, struc /* value/position */ if (items[u].flags & LYS_IS_ENUM) { - sprintf(buf, "%" PRId32, items[u].value); + snprintf(buf, sizeof buf, "%" PRId32, items[u].value); LY_CHECK_GOTO(rc = lyd_new_term(par_list, NULL, "value", buf, 0, NULL), cleanup); } else { - sprintf(buf, "%" PRIu32, items[u].position); + snprintf(buf, sizeof buf, "%" PRIu32, items[u].position); LY_CHECK_GOTO(rc = lyd_new_term(par_list, NULL, "position", buf, 0, NULL), cleanup); } @@ -3625,7 +3625,7 @@ schema_diff_node_type(const struct lysc_type *type, struct lyd_node *type_par) type_dec = (const struct lysc_type_dec *)type; /* fraction-digits */ - sprintf(buf, "%" PRIu8, type_dec->fraction_digits); + snprintf(buf, sizeof buf, "%" PRIu8, type_dec->fraction_digits); LY_CHECK_GOTO(rc = lyd_new_term(type_par, NULL, "fraction-digits", buf, 0, NULL), cleanup); /* range */ @@ -3828,13 +3828,13 @@ schema_diff_node_stmts(const struct lysc_node *node, ly_bool gen_local, struct l max = llist->max; } if (min > 0) { - sprintf(buf, "%" PRIu32, min); + snprintf(buf, sizeof buf, "%" PRIu32, min); if ((rc = lyd_new_term(change_cont, NULL, "min-elements", buf, 0, NULL))) { goto cleanup; } } if (max < UINT32_MAX) { - sprintf(buf, "%" PRIu32, max); + snprintf(buf, sizeof buf, "%" PRIu32, max); if ((rc = lyd_new_term(change_cont, NULL, "max-elements", buf, 0, NULL))) { goto cleanup; } diff --git a/src/tree_data_common.c b/src/tree_data_common.c index 9fc0159d0..6089b6559 100644 --- a/src/tree_data_common.c +++ b/src/tree_data_common.c @@ -1648,7 +1648,7 @@ ly_time_time2str(time_t time, const char *fractions_s, char **str) zonediff_s = ly_time_tz_offset_at(time); zonediff_h = zonediff_s / 60 / 60; zonediff_m = zonediff_s / 60 % 60; - sprintf(zoneshift, "%+03d:%02d", zonediff_h, zonediff_m < 0 ? -zonediff_m : zonediff_m); + snprintf(zoneshift, sizeof zoneshift, "%+03d:%02d", zonediff_h, zonediff_m < 0 ? -zonediff_m : zonediff_m); /* print */ if (asprintf(str, "%04d-%02d-%02dT%02d:%02d:%02d%s%s%s", @@ -1698,7 +1698,7 @@ ly_time_ts2str(const struct timespec *ts, char **str) /* convert nanoseconds to fractions of a second */ if (ts->tv_nsec) { - sprintf(frac_buf, "%09ld", ts->tv_nsec); + snprintf(frac_buf, sizeof frac_buf, "%09ld", ts->tv_nsec); } return ly_time_time2str(ts->tv_sec, ts->tv_nsec ? frac_buf : NULL, str); diff --git a/src/tree_schema.c b/src/tree_schema.c index 85b8833fa..bcf0f17ae 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -1000,7 +1000,7 @@ lysc_path_until(const struct lysc_node *node, const struct lysc_node *parent, LY path = NULL; } else if (len == 0) { if (buffer) { - strcpy(buffer, "/"); + snprintf(buffer, buflen, "/"); } else { free(path); path = strdup("/");