diff options
author | Justus Winter <justus@g10code.com> | 2016-07-26 18:29:01 +0200 |
---|---|---|
committer | Justus Winter <justus@g10code.com> | 2016-07-26 18:37:37 +0200 |
commit | b2572b0c386fd12ac6581fcce72f8d48cbfd27c7 (patch) | |
tree | 562942c29a59deae8c35a79079562d8d9022ca9c /common/iobuf.c | |
parent | gpgscm: Do not shadow common function name in catch macro. (diff) | |
download | gnupg2-b2572b0c386fd12ac6581fcce72f8d48cbfd27c7.tar.xz gnupg2-b2572b0c386fd12ac6581fcce72f8d48cbfd27c7.zip |
common: Fix iobuf_peek corner case.
Previously, iobuf_peek on a file smaller than 'buflen' would hang.
* common/iobuf.c (underflow): Generalize by adding a target parameter.
(iobuf_peek): Use this to prevent looping here.
* tests/openpgp/Makefile.am (TESTS): Add new test.
* tests/openpgp/setup.scm (dearmor): Move function...
* tests/openpgp/defs.scm (dearmor): ... here.
* tests/openpgp/issue2419.scm: New file.
* tests/openpgp/samplemsgs/issue2419.asc: Likewise.
GnuPG-bug-id: 2419
Signed-off-by: Justus Winter <justus@g10code.com>
Diffstat (limited to 'common/iobuf.c')
-rw-r--r-- | common/iobuf.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/common/iobuf.c b/common/iobuf.c index f3d67b474..9d582ca20 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -162,6 +162,7 @@ static int special_names_enabled; /* Local prototypes. */ static int underflow (iobuf_t a, int clear_pending_eof); +static int underflow_target (iobuf_t a, int clear_pending_eof, size_t target); static int translate_file_handle (int fd, int for_write); /* Sends any pending data to the filter's FILTER function. Note: this @@ -1769,12 +1770,23 @@ iobuf_pop_filter (iobuf_t a, int (*f) (void *opaque, int control, /**************** - * read underflow: read more bytes into the buffer and return + * read underflow: read at least one byte into the buffer and return * the first byte or -1 on EOF. */ static int underflow (iobuf_t a, int clear_pending_eof) { + return underflow_target (a, clear_pending_eof, 1); +} + + +/**************** + * read underflow: read TARGET bytes into the buffer and return + * the first byte or -1 on EOF. + */ +static int +underflow_target (iobuf_t a, int clear_pending_eof, size_t target) +{ size_t len; int rc; @@ -1799,7 +1811,7 @@ underflow (iobuf_t a, int clear_pending_eof) memmove (a->d.buf, &a->d.buf[a->d.start], a->d.len); a->d.start = 0; - if (a->d.len == 0 && a->filter_eof) + if (a->d.len < target && a->filter_eof) /* The last time we tried to read from this filter, we got an EOF. We couldn't return the EOF, because there was buffered data. Since there is no longer any buffered data, return the @@ -2090,7 +2102,7 @@ iobuf_peek (iobuf_t a, byte * buf, unsigned buflen) request. */ while (buflen > a->d.len - a->d.start) { - if (underflow (a, 0) == -1) + if (underflow_target (a, 0, buflen) == -1) /* EOF. We can't read any more. */ break; |