Bruno, Paul, I have followed your suggestions and amended them in the patch.
It rollbacks to the previous code and reads from the stream on overflows. Also, as suggested, I have added another check for overflow in the existing code. Thanks, Giuseppe >From c0f45017bded0d958ec430a54b1fb1b29098f8ec Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano <gscriv...@gnu.org> Date: Tue, 3 Aug 2010 15:40:19 +0200 Subject: [PATCH] read-file: Avoid memory reallocations with regular files. * modules/read-file (Depends-on): Add ftello and malloc-posix. * lib/read-file.c: Include <sys/types.h>, <sys/stat.h>, <unistd.h>, <stdio.h>. (fread_file): With regular files, use the remaining length as the initial buffer size. Check against overflow. --- ChangeLog | 9 +++++++++ lib/read-file.c | 42 +++++++++++++++++++++++++++++++++++++++++- modules/read-file | 2 ++ 3 files changed, 52 insertions(+), 1 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4d24a34..80061a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-08-03 Giuseppe Scrivano <gscriv...@gnu.org> + + read-file: Avoid memory reallocations with regular files. + * modules/read-file (Depends-on): Add ftello and malloc-posix. + * lib/read-file.c: Include <sys/types.h>, <sys/stat.h>, + <unistd.h>, <stdio.h>. + (fread_file): With regular files, use the remaining length as the + initial buffer size. Check against overflow. + 2010-08-01 Bruno Haible <br...@clisp.org> Integrate the regex documentation. diff --git a/lib/read-file.c b/lib/read-file.c index 6b655db..b92c3f1 100644 --- a/lib/read-file.c +++ b/lib/read-file.c @@ -18,6 +18,14 @@ #include <config.h> +/* Get fstat. */ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +/* Get ftello. */ +#include <stdio.h> + #include "read-file.h" /* Get realloc, free. */ @@ -38,6 +46,31 @@ fread_file (FILE * stream, size_t * length) size_t alloc = 0; size_t size = 0; int save_errno; + struct stat st; + + do + { + off_t alloc_off, pos; + + if (fstat (fileno (stream), &st) < 0 || !S_ISREG (st.st_mode)) + break; + + pos = ftello (stream); + if (pos < 0 || pos > st.st_size) + break; + + alloc_off = st.st_size - pos; + if (alloc_off - (off_t) (size_t) alloc_off + || (size_t) alloc_off + 1 < (size_t) alloc_off) + break; + + alloc = alloc_off + 1; + + buf = malloc (alloc); + if (!buf) + return NULL; + } + while (0); for (;;) { @@ -47,8 +80,15 @@ fread_file (FILE * stream, size_t * length) if (size + BUFSIZ + 1 > alloc) { char *new_buf; + size_t new_alloc = alloc + alloc / 2; + + if (new_alloc < alloc) + { + save_errno = ENOMEM; + break; + } - alloc += alloc / 2; + alloc = new_alloc; if (alloc < size + BUFSIZ + 1) alloc = size + BUFSIZ + 1; diff --git a/modules/read-file b/modules/read-file index e302940..64c1d63 100644 --- a/modules/read-file +++ b/modules/read-file @@ -7,6 +7,8 @@ lib/read-file.c m4/read-file.m4 Depends-on: +ftello +malloc-posix realloc-posix configure.ac: -- 1.7.1