avoid updating caller's size when getdelim fails to realloc
authorRich Felker <dalias@aerifal.cx>
Sun, 20 Dec 2015 04:43:31 +0000 (23:43 -0500)
committerRich Felker <dalias@aerifal.cx>
Sun, 20 Dec 2015 04:43:31 +0000 (23:43 -0500)
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.

src/stdio/getdelim.c

index 307749080a9d4dd77432dfdeaa5e3918ea0c76bf..813b09fcfbc2b91b991158b3721160464b5e411f 100644 (file)
@@ -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;