]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
Add file buffer pool support to fgetln()
authorGuillem Jover <guillem@hadrons.org>
Sun, 25 Nov 2012 21:09:43 +0000 (22:09 +0100)
committerGuillem Jover <guillem@hadrons.org>
Mon, 27 May 2013 00:12:51 +0000 (02:12 +0200)
This avoids buffer overwrites during concurrent or intermixed calls to
fgetln() when using more than one different stream (currently 32), which
the original interface supports natively by using an internal buffer
from the FILE structure. Although this workaround is rudimentary, it
should cover most of the theoretically problematic cases.

COPYING
src/fgetln.c

diff --git a/COPYING b/COPYING
index b84fb6f40ea2523d924d5c5ba181770e7749b436..5a42e5052af678d1fac2711c45f25c593f0ce697 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -66,7 +66,7 @@ for man/arc4random.3, man/tree.3 and man/getprogname.3.
 The rest of the licenses apply to code and/or man pages.
 
 
-    Copyright © 2004-2006, 2008-2011 Guillem Jover <guillem@hadrons.org>
+    Copyright © 2004-2006, 2008-2012 Guillem Jover <guillem@hadrons.org>
     Copyright © 2005 Hector Garcia Alvarez
     Copyright © 2005 Aurelien Jarno
     Copyright © 2006 Robert Millan
index 183e853a15fc704d6fd54291215d18f554fb220d..6de804bb75d58cd71cbf7ddcbe98dfdd32d1d449 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2005 Hector Garcia Alvarez
- * Copyright © 2005, 2008, 2009, 2011 Guillem Jover <guillem@hadrons.org>
+ * Copyright © 2005, 2008-2012 Guillem Jover <guillem@hadrons.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include <string.h>
 
 #ifdef HAVE_GETLINE
+struct filebuf {
+       FILE *fp;
+       char *buf;
+       size_t len;
+};
+
+#define FILEBUF_POOL_ITEMS 32
+
+static struct filebuf fb_pool[FILEBUF_POOL_ITEMS];
+static int fb_pool_cur;
+
 char *
 fgetln(FILE *stream, size_t *len)
 {
-       static char *line = NULL;
-       static size_t line_len = 0;
+       struct filebuf *fb;
        ssize_t nread;
 
-       nread = getline(&line, &line_len, stream);
+       /* Try to diminish the possibility of several fgetln() calls being
+        * used on different streams, by using a pool of buffers per file. */
+       fb = &fb_pool[fb_pool_cur];
+       if (fb->fp != stream && fb->fp != NULL) {
+               fb_pool_cur++;
+               fb_pool_cur %= FILEBUF_POOL_ITEMS;
+               fb = &fb_pool[fb_pool_cur];
+       }
+       fb->fp = stream;
+
+       nread = getline(&fb->buf, &fb->len, stream);
        /* Note: the getdelim/getline API ensures nread != 0. */
        if (nread == -1) {
                *len = 0;
                return NULL;
        } else {
                *len = (size_t)nread;
-               return line;
+               return fb->buf;
        }
 }
 #else