fix potential PROTECT/UNPROTECT issues in C code - #469
Merged
Conversation
jeroen
reviewed
Aug 5, 2026
| Rf_errorcall(R_NilValue, "%s", errbuf); | ||
| } | ||
| SEXP out = ParseValue(node, bigint); | ||
| SEXP out = PROTECT(ParseValue(node, bigint)); |
Owner
There was a problem hiding this comment.
This is really not needed, yajl_tree_free is not an R call so it won't have any effect on gc.
Contributor
Author
There was a problem hiding this comment.
Thanks, you're right -- this was just meant to be defensive. The only potential issue is in push_parser.c, since (in theory) the evaluation order of the expressions is undefined. I'll trim this PR to the minimal set of changes that are worth considering here.
Per review feedback, drop the defensive-only PROTECT additions in parse.c, r-base64.c, and row_collapse.c -- none of those windows contain allocating calls. Also drop the UNPROTECT before the goto in push_parser.c, since Rf_error() unwinds the protection stack itself. Keep the evaluation-order fix in push_parser.c, and NUL-termination of the error buffer after strncpy.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This fixes a PROTECT-related issue in
push_parser.c, found via a manual audit.PROTECT()calls were nested inside the argument list ofRf_lang4(). Since C argument evaluation order is unspecified, a compiler may evaluateRf_allocVector()andRf_ScalarInteger()before eitherPROTECT()runs, leaving a fresh allocation unprotected while another allocation (and potentially GC) occurs. The objects are now allocated and protected in separate statements.Also guarantees NUL-termination of the error buffer after
strncpy(), which does not terminate on truncation.This PR originally also added defensive
PROTECT()calls inparse.c,r-base64.c, androw_collapse.c. As @jeroen noted in review, those windows contain no allocating calls, so the protection had no effect; they've been dropped.Tested with
R CMD INSTALLand the testthat suite, and exercised the touched paths (including the parse-error path) undergctorture(TRUE).