bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] read-file: Avoid memory reallocations with seekable files.


From: Giuseppe Scrivano
Subject: Re: [PATCH] read-file: Avoid memory reallocations with seekable files.
Date: Wed, 04 Aug 2010 19:23:51 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux)

Paul Eggert <address@hidden> writes:

> It would be clearer without the casts.  (Casts are often
> overkill in C; they disable too much checking.)  Also, I'm still
> dubious about going ahead with a file that's too
> large to fit into memory.

Here is another version, it fails with ENOMEM on files that don't fit
into memory.

Cheers,
Giuseppe



>From 985a52e1b654fa904e964977b24306fb97c586e7 Mon Sep 17 00:00:00 2001
From: Giuseppe Scrivano <address@hidden>
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>, <stdint.h>.
(fread_file): With regular files, use the remaining length as the
initial buffer size.  Check against overflow.
---
 ChangeLog         |    9 +++++++++
 lib/read-file.c   |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
 modules/read-file |    2 ++
 3 files changed, 57 insertions(+), 1 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4d24a34..95b9fab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2010-08-03  Giuseppe Scrivano  <address@hidden>
+
+       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>, <stdint.h>.
+       (fread_file): With regular files, use the remaining length as the
+       initial buffer size.  Check against overflow.
+
 2010-08-01  Bruno Haible  <address@hidden>
 
        Integrate the regex documentation.
diff --git a/lib/read-file.c b/lib/read-file.c
index 6b655db..628def1 100644
--- a/lib/read-file.c
+++ b/lib/read-file.c
@@ -20,6 +20,17 @@
 
 #include "read-file.h"
 
+/* Get fstat.  */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Get ftello.  */
+#include <stdio.h>
+
+/* Get SIZE_MAX.  */
+#include <stdint.h>
+
 /* Get realloc, free. */
 #include <stdlib.h>
 
@@ -38,6 +49,33 @@ 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 (SIZE_MAX <= alloc_off)
+        {
+          errno = ENOMEM;
+          return NULL;
+        }
+
+      alloc = alloc_off + 1;
+
+      buf = malloc (alloc);
+      if (!buf)
+        return NULL;
+    }
+  while (0);
 
   for (;;)
     {
@@ -47,8 +85,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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]