Skip to content

data REFACTOR build strings with measured, bounded appends - #2625

Merged
michalvasko merged 1 commit into
CESNET:develfrom
aravindor:refactor-bounded-strings
Nov 10, 2026
Merged

michalvasko merged 1 commit into
CESNET:develfrom
aravindor:refactor-bounded-strings

Conversation

@aravindor

Copy link
Copy Markdown

The XPath string cast, concat() and the JSON predicate builder, lyd_path(), the LYB feature check and the CBOR number conversion grow strings by summing each length by hand and then writing with sprintf() / strcpy() / strcat(). Every one of those sums has to keep matching its format string, and these paths format values that come from parsed data. They are all correct today; this removes the hand-sized math so it cannot drift, the same way #2591 did for the type plugins.

  • xpath.c: new cast_string_append() measures the text with vsnprintf() and writes it bounded, keeping the step growth of cast_string_realloc(). concat() and the predicate builder use the existing ly_append_str().
  • tree_data.c: new lyd_path_str_append() does the same on top of lyd_path_str_enlarge(), so a static buffer still returns LY_EINCOMPLETE. The position predicate no longer needs a temporary asprintf().
  • parser_lyb.c: the enabled-feature lists use ly_append_str(). This also fixes lyb_check_mod_features() returning LY_SUCCESS when allocating the error message failed, which accepted data with mismatched features. The revision string uses snprintf().
  • parser_cbor.c, parser_common.c: snprintf() bounded by the allocation, and strdup() in place of malloc() + strcpy().

Output is unchanged. Built on devel with -fsanitize=address,undefined; the full test suite passes (71/71), no sanitizer reports, and make format-check is clean.

@michalvasko michalvasko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the conflicts and the few issues. Otherwise seems fine, thanks.

Comment thread src/xpath.c Resolved
Comment thread src/xpath.c Resolved
Comment thread src/tree_data.c Resolved
Comment thread src/tree_data.c Resolved
The XPath string cast, concat() and the JSON predicate, lyd_path(), the LYB
feature check and the CBOR number conversion grew strings by summing each
length by hand and writing with sprintf()/strcpy()/strcat(). The sums are
correct today but each has to keep matching its format string, and these paths
format values that come from parsed data. Measure the formatted output and
write it bounded instead, as CESNET#2591 did for the type plugins. Output is
unchanged.

 - xpath.c: new cast_string_append() measures with vsnprintf() and keeps the
   step growth of the former cast_string_realloc(), now inlined into it.
   concat() and the predicate builder use ly_append_str().
 - tree_data.c: new lyd_path_str_append() with the former lyd_path_str_enlarge()
   inlined, so a static buffer still returns LY_EINCOMPLETE.
 - parser_lyb.c: feature lists use ly_append_str(); the revision string uses
   snprintf(). This also fixes lyb_check_mod_features() returning LY_SUCCESS
   when allocating the error message failed, which accepted mismatched features.
 - parser_cbor.c, parser_common.c: snprintf() bounded by the allocation,
   strdup() instead of malloc()+strcpy().
@aravindor
aravindor force-pushed the refactor-bounded-strings branch from 9b18999 to 650a932 Compare November 9, 2026 16:46
@aravindor

Copy link
Copy Markdown
Author

Thanks for the review. Updated:

  • Rebased onto current devel (it had rebased the XPath node-moveto refactor since I opened this).
  • cast_string_realloc() is now inlined into cast_string_append(), and lyd_path_str_enlarge() into lyd_path_str_append().
  • Moved both local prototypes to the top of their files.

On your suggestion to fold this into ly_append_str() with an optional context: I kept the small cast_string_append() wrapper so the XPath string cast keeps growing the buffer in LYXP_STRING_CAST_SIZE_STEP chunks, which matters because it appends one piece per node. Routing it through ly_append_str() would reallocate on every append and would also touch the other callers. Happy to change it if you'd still prefer the unified helper.

@michalvasko

Copy link
Copy Markdown
Member

Looks okay now, thanks.

@michalvasko
michalvasko merged commit edad24a into CESNET:devel Nov 10, 2026
11 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants