summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2015-12-19 23:43:31 -0500
committerRich Felker <dalias@aerifal.cx>2015-12-19 23:43:31 -0500
commitd87f0a9a95f0a1228ee5579e5822a8c93bc96823 (patch)
tree04e8b2769da6dfde2239e38ff7481001e0c34960
parent42216742cd69e52e70aeb1d14498a8145872de52 (diff)
downloadmusl-d87f0a9a95f0a1228ee5579e5822a8c93bc96823.tar.gz
avoid updating caller's size when getdelim fails to realloc
getdelim was updating *n, the caller's stored buffer size, before calling realloc. if getdelim then failed due to realloc failure, the caller would see in *n a value larger than the actual size of the allocated block, and use of that value is unsafe. in particular, passing it again to getdelim is unsafe. now, temporary storage is used for the desired new size, and *n is not written until realloc succeeds.
-rw-r--r--src/stdio/getdelim.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/src/stdio/getdelim.c b/src/stdio/getdelim.c
index 30774908..813b09fc 100644
--- a/src/stdio/getdelim.c
+++ b/src/stdio/getdelim.c
@@ -29,15 +29,16 @@ ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restric
k = z ? z - f->rpos + 1 : f->rend - f->rpos;
if (i+k+1 >= *n) {
if (k >= SIZE_MAX/2-i) goto oom;
- *n = i+k+2;
- if (*n < SIZE_MAX/4) *n *= 2;
- tmp = realloc(*s, *n);
+ size_t m = i+k+2;
+ if (m < SIZE_MAX/4) m *= 2;
+ tmp = realloc(*s, m);
if (!tmp) {
- *n = i+k+2;
- tmp = realloc(*s, *n);
+ m = i+k+2;
+ tmp = realloc(*s, m);
if (!tmp) goto oom;
}
*s = tmp;
+ *n = m;
}
memcpy(*s+i, f->rpos, k);
f->rpos += k;