Skip to content

Commit 1c34139

Browse files
committed
memrecycle: allocate temporary on the R heap
This avoids a memory leak in case growVector or hash_set fails.
1 parent 95e91af commit 1c34139

File tree

1 file changed

+3
-8
lines changed

1 file changed

+3
-8
lines changed

src/assign.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -794,13 +794,8 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
794794
source = newSource;
795795
for (int k=0; k<nTargetLevels; ++k) hash_set(marks, targetLevelsD[k], 0); // don't need those anymore
796796
if (nAdd) {
797-
// cannot grow the levels yet as that would be R call which could fail to alloc and we have no hook to clear up
798-
SEXP *temp = malloc(sizeof(*temp) * nAdd);
799-
if (!temp) {
800-
// # nocov start
801-
error(_("Unable to allocate working memory of %zu bytes to combine factor levels"), nAdd*sizeof(SEXP *));
802-
// # nocov end
803-
}
797+
void *vmax = vmaxget();
798+
SEXP *temp = (SEXP *)R_alloc(nAdd, sizeof(*temp));
804799
for (int k=0, thisAdd=0; thisAdd<nAdd; ++k) { // thisAdd<nAdd to stop early when the added ones are all reached
805800
SEXP s = sourceLevelsD[k];
806801
int tl = hash_lookup(marks, s, 0);
@@ -814,7 +809,7 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
814809
for (int k=0; k<nAdd; ++k) {
815810
SET_STRING_ELT(targetLevels, nTargetLevels+k, temp[k]);
816811
}
817-
free(temp);
812+
vmaxset(vmax);
818813
} else {
819814
// all source levels were already in target levels, but not with the same integers; we're done
820815
}

0 commit comments

Comments
 (0)