Skip to content

Commit 3b9a572

Browse files
committed
Safety checks in R_resizeVector() backport
1 parent 14c1148 commit 3b9a572

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

src/data.table.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,19 @@
8989

9090
// TODO(R>=4.6.0): remove the SVN revision check
9191
#if R_VERSION < R_Version(4, 6, 0) || R_SVN_REVISION < 89077
92+
# define BACKPORT_RESIZABLE_API
9293
# define R_allocResizableVector(type, maxlen) R_allocResizableVector_(type, maxlen)
9394
# define R_duplicateAsResizable(x) R_duplicateAsResizable_(x)
94-
# define R_resizeVector(x, newlen) SETLENGTH(x, newlen)
9595
# define R_maxLength(x) R_maxLength_(x)
9696
static inline R_xlen_t R_maxLength_(SEXP x) {
9797
return IS_GROWABLE(x) ? TRUELENGTH(x) : XLENGTH(x);
9898
}
9999
# define R_isResizable(x) R_isResizable_(x)
100100
static inline bool R_isResizable_(SEXP x) {
101-
// IS_GROWABLE also checks for XLENGTH < TRUELENGTH
102-
return (LEVELS(x) & 0x20) && TRUELENGTH(x);
101+
// IS_GROWABLE checks for XLENGTH < TRUELENGTH instead
102+
return (LEVELS(x) & 0x20) && XLENGTH(x) <= TRUELENGTH(x);
103103
}
104+
# define R_resizeVector(x, newlen) R_resizeVector_(x, newlen)
104105
#endif
105106

106107
// init.c
@@ -338,8 +339,11 @@ bool perhapsDataTable(SEXP x);
338339
SEXP perhapsDataTableR(SEXP x);
339340
SEXP frev(SEXP x, SEXP copyArg);
340341
NORET void internal_error(const char *call_name, const char *format, ...);
342+
#ifdef BACKPORT_RESIZABLE_API
341343
SEXP R_allocResizableVector_(SEXPTYPE type, R_xlen_t maxlen);
342344
SEXP R_duplicateAsResizable_(SEXP x);
345+
void R_resizeVector_(SEXP x, R_xlen_t newlen);
346+
#endif
343347

344348
// types.c
345349
char *end(char *start);

src/utils.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,7 @@ void internal_error(const char *call_name, const char *format, ...) {
660660
error("%s %s: %s. %s", _("Internal error in"), call_name, buff, _("Please report to the data.table issues tracker."));
661661
}
662662

663+
#ifdef BACKPORT_RESIZABLE_API
663664
SEXP R_allocResizableVector_(SEXPTYPE type, R_xlen_t maxlen) {
664665
SEXP ret = allocVector(type, maxlen);
665666
SET_TRUELENGTH(ret, maxlen);
@@ -674,3 +675,12 @@ SEXP R_duplicateAsResizable_(SEXP x) {
674675
SET_GROWABLE_BIT(ret);
675676
return ret;
676677
}
678+
679+
void R_resizeVector_(SEXP x, R_xlen_t newlen) {
680+
if (!R_isResizable(x))
681+
internal_error(__func__, "attempt to resize a non-resizable vector");
682+
if (newlen > XTRUELENGTH(x))
683+
internal_error(__func__, "newlen=%g exceeds maxlen=%g", (double)newlen, (double)R_maxLength(x));
684+
SETLENGTH(x, newlen);
685+
}
686+
#endif

0 commit comments

Comments
 (0)