Skip to content

Enhance memory safety with validity checks on jv values #3347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

izroxxet
Copy link

This pull request addresses a memory safety issue in the jv_object_merge_recursive function, where potentially uninitialized values may be accessed without proper validation.

  • CWE-457: Use of Uninitialized Variable

    In jv_object_merge_recursive, the result of jv_object_get(...) was previously assumed to be valid. This could result in undefined behavior if an invalid jv value is passed to JVP_HAS_KIND.

Fix:

  • Introduced a separate variable (elem_valid) to store the result of jv_is_valid(elem)
  • Updated conditional logic to ensure elem is only accessed when it is confirmed to be valid

This change helps prevent segmentation faults and unpredictable behavior caused by unsafe dereferencing of invalid jv values. It improves the overall robustness and stability of the system, especially in edge cases involving malformed or incomplete input.

Fixes #3346

@itchyny
Copy link
Contributor

itchyny commented Jun 13, 2025

I don't understand. When elem is invalid, JVP_HAS_KIND(elem, JV_KIND_OBJECT) is not evaluated due to short-circuit evaluation. Also, I think jv_is_valid(elem) && can be removed, because jv_is_valid(elem) is equals to JVP_KIND(elem) != JV_KIND_INVALID.

@wader
Copy link
Member

wader commented Jun 13, 2025

How could you end up with an object that has invalid values (or keys?)? possible thru filter expression or only using libjq API?

@izroxxet
Copy link
Author

@itchyny
Thanks for the insightful comment!

You're right that due to short-circuit evaluation, JVP_HAS_KIND(elem, ...) won't be evaluated if jv_is_valid(elem) is false. And yes, technically jv_is_valid() is equivalent to checking JVP_KIND(elem) != JV_KIND_INVALID.

However, the patch uses jv_is_valid(elem) explicitly to:

  • Make the intent clearer for future readers and maintainers,
  • Avoid relying on internal macro behavior (JVP_HAS_KIND),
  • And allow for easier debugging (e.g., storing the validity in a named variable like elem_valid).

So while it might be slightly redundant, I believe it improves code clarity and robustness overall. Open to further discussion though!

@izroxxet
Copy link
Author

@wader
Great question!

In typical jq filter usage, it's quite rare to end up with an object containing invalid keys or values — jq generally prevents such states.

However, it's possible in a few edge cases:

  • When building up objects manually using complex filters (e.g., reduce, foreach) that may introduce invalid values via conditional expressions.
  • More importantly, when using the libjq C API directly. If a developer incorrectly inserts jv_invalid() into an object or mishandles the result of a failed operation (like jv_object_get() or jv_object_set()), it's possible to construct objects containing invalid jvs.

So this patch is primarily a safeguard for robustness — especially relevant when libjq is used programmatically or in embedded environments, but it also protects against any corner-case behavior that may arise in advanced jq usage.

@itchyny
Copy link
Contributor

itchyny commented Jun 13, 2025

Nothing is unpredictable behavior here.

@itchyny itchyny closed this Jun 13, 2025
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.

Fix uninitialized variable use in jv_object_merge_recursive to improve memory safety
3 participants