Skip to content

Commit 801b7f3

Browse files
committed
Protect token while unwinding the stack
Because R code might run in C++ destructors
1 parent 985c94b commit 801b7f3

File tree

3 files changed

+10
-7
lines changed

3 files changed

+10
-7
lines changed

inst/include/Rcpp/api/meat/Rcpp_eval.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,15 @@ namespace internal {
3939

4040
inline void Rcpp_maybe_throw(void* data, Rboolean jump) {
4141
if (jump) {
42-
throw LongjumpException(static_cast<SEXP>(data));
42+
SEXP token = static_cast<SEXP>(data);
43+
44+
// Keep the token protected while unwinding because R code might run
45+
// in C++ destructors. Can't use PROTECT() for this because
46+
// UNPROTECT() might be called in a destructor, for instance if a
47+
// Shield<SEXP> is on the stack.
48+
::R_PreserveObject(token);
49+
50+
throw LongjumpException(token);
4351
}
4452
}
4553

inst/include/Rcpp/exceptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ namespace Rcpp {
119119
};
120120

121121
inline void resumeJump(SEXP token) {
122+
::R_ReleaseObject(token);
122123
#if (defined(RCPP_PROTECTED_EVAL) && defined(R_VERSION) && R_VERSION >= R_Version(3, 5, 0))
123124
::R_ContinueUnwind(token);
124125
#endif

inst/unitTests/cpp/misc.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,6 @@ SEXP testEvalUnwindImpl(RObject expr, Environment env, LogicalVector indicator)
249249
return Rcpp::Rcpp_fast_eval(expr, env);
250250
}
251251

252-
// [[Rcpp::export]]
253-
SEXP testLongjumpException() {
254-
throw Rcpp::internal::LongjumpException(R_NilValue);
255-
return R_NilValue;
256-
}
257-
258252
// [[Rcpp::export]]
259253
SEXP testSendInterrupt() {
260254
Rf_onintr();

0 commit comments

Comments
 (0)