- size_t newlinesize =
- (*linesize > MIN_CHUNK ? 2 * *linesize : *linesize + MIN_CHUNK);
- char *p;
-
- if (! (*linesize < newlinesize && newlinesize <= nmax))
- newlinesize = nmax;
-
- *linesize = newlinesize;
- nbytes_avail = *linesize + *lineptr - read_pos;
- p = realloc (*lineptr, *linesize);
- if (!p)
- return -1;
- *lineptr = p;
- read_pos = *linesize - nbytes_avail + *lineptr;
+ /* Grow size proportionally, not linearly, to avoid O(n^2)
+ running time. */
+ size_t newsize = size < MIN_CHUNK ? size + MIN_CHUNK : 2 * size;
+ char *newptr;
+
+ /* Increase newsize so that it becomes
+ >= (read_pos - ptr) + buffer_len. */
+ if (newsize - (read_pos - ptr) < buffer_len + 1)
+ newsize = (read_pos - ptr) + buffer_len + 1;
+ /* Respect nmax. This handles possible integer overflow. */
+ if (! (size < newsize && newsize <= nmax))
+ newsize = nmax;
+
+ if (GETNDELIM2_MAXIMUM < newsize - offset)
+ {
+ size_t newsizemax = offset + GETNDELIM2_MAXIMUM + 1;
+ if (size == newsizemax)
+ goto unlock_done;
+ newsize = newsizemax;
+ }
+
+ nbytes_avail = newsize - (read_pos - ptr);
+ newptr = realloc (ptr, newsize);
+ if (!newptr)
+ goto unlock_done;
+ ptr = newptr;
+ size = newsize;
+ read_pos = size - nbytes_avail + ptr;