Skip to content

Commit ead1859

Browse files
committed
chmatchdup: allocate temporaries on the R heap
Prevent memory leak in case hash_set() causes a long jump.
1 parent 1c34139 commit ead1859

File tree

1 file changed

+7
-11
lines changed

1 file changed

+7
-11
lines changed

src/chmatch.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,14 @@ static SEXP chmatchMain(SEXP x, SEXP table, int nomatch, bool chin, bool chmatch
115115
// For example: A,B,C,B,D,E,A,A => A(TL=1),B(2),C(3),D(4),E(5) => dupMap 1 2 3 5 6 | 8 7 4
116116
// dupLink 7 8 | 6 (blank=0)
117117
unsigned int mapsize = tablelen+nuniq; // lto compilation warning #5760 // +nuniq to store a 0 at the end of each group
118-
int *counts = calloc(nuniq, sizeof(*counts));
119-
int *map = calloc(mapsize, sizeof(*map));
120-
if (!counts || !map) {
121-
// # nocov start
122-
free(counts); free(map);
123-
error(_("Failed to allocate %"PRIu64" bytes working memory in chmatchdup: length(table)=%d length(unique(table))=%d"), ((uint64_t)tablelen*2+nuniq)*sizeof(int), tablelen, nuniq);
124-
// # nocov end
125-
}
118+
void *vmax = vmaxget();
119+
int *counts = (int *)R_alloc(nuniq, sizeof(*counts));
120+
if (nuniq) memset(counts, 0, sizeof(*counts) * nuniq);
121+
int *map = (int *)R_alloc(mapsize, sizeof(*map));
122+
if (mapsize) memset(map, 0, sizeof(*map) * mapsize);
126123
for (int i=0; i<tablelen; ++i) counts[-hash_lookup(marks, td[i], 0)-1]++;
127124
for (int i=0, sum=0; i<nuniq; ++i) { int tt=counts[i]; counts[i]=sum; sum+=tt+1; }
128-
for (int i=0; i<tablelen; ++i) map[counts[-hash_lookup(marks, td[i], 0)-1]++] = i+1; // 0 is left ending each group thanks to the calloc
125+
for (int i=0; i<tablelen; ++i) map[counts[-hash_lookup(marks, td[i], 0)-1]++] = i+1; // 0 is left ending each group thanks to the memset
129126
for (int i=0, last=0; i<nuniq; ++i) {int tt=counts[i]+1; counts[i]=last; last=tt;} // rewind counts to the beginning of each group
130127
for (int i=0; i<xlen; ++i) {
131128
int u = hash_lookup(marks, xd[i], 0);
@@ -136,8 +133,7 @@ static SEXP chmatchMain(SEXP x, SEXP table, int nomatch, bool chin, bool chmatch
136133
}
137134
ansd[i] = nomatch;
138135
}
139-
free(counts);
140-
free(map);
136+
vmaxset(vmax);
141137
} else if (chin) {
142138
#pragma omp parallel for num_threads(getDTthreads(xlen, true))
143139
for (int i=0; i<xlen; i++) {

0 commit comments

Comments
 (0)