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>
This commit is contained in:
Justus Winter 2016-07-26 18:29:01 +02:00
parent 046338b849
commit b2572b0c38
6 changed files with 58 additions and 11 deletions

View File

@ -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,11 +1770,22 @@ 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;

View File

@ -84,6 +84,7 @@ TESTS = setup.scm \
ssh.scm \
issue2015.scm \
issue2346.scm \
issue2419.scm \
finish.scm

View File

@ -133,6 +133,13 @@
(string-split
(call-popen `(,@GPG --with-colons ,@args) input) #\newline)))
;; Dearmor a file.
(define (dearmor source-name sink-name)
(pipe:do
(pipe:open source-name (logior O_RDONLY O_BINARY))
(pipe:spawn `(,@GPG --dearmor))
(pipe:write-to sink-name (logior O_WRONLY O_CREAT O_BINARY) #o600)))
(let ((verbose (string->number (getenv "verbose"))))
(if (number? verbose)
(*set-verbose!* verbose)))

28
tests/openpgp/issue2419.scm Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env gpgscm
;; Copyright (C) 2016 g10 Code GmbH
;;
;; This file is part of GnuPG.
;;
;; GnuPG is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3 of the License, or
;; (at your option) any later version.
;;
;; GnuPG is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, see <http://www.gnu.org/licenses/>.
(load (with-path "defs.scm"))
(info "Checking iobuf_peek corner case (issue2419)...")
(lettmp
(onebyte)
(dearmor (in-srcdir "samplemsgs/issue2419.asc") onebyte)
(catch (assert (string-contains? *error* "invalid packet"))
(call-popen `(,@GPG --list-packets ,onebyte) "")
(error "Expected an error but got none")))

View File

@ -0,0 +1,7 @@
-----BEGIN PGP ARMORED FILE-----
Version: GnuPG v2
Comment: Use "gpg --dearmor" for unpacking
AA==
=YWnT
-----END PGP ARMORED FILE-----

View File

@ -55,14 +55,6 @@
CLOSED_FD fd STDERR_FILENO)))
'(500 9000 32000 80000))
(define (dearmor source-name sink-name)
(pipe:do
(pipe:open source-name (logior O_RDONLY O_BINARY))
(pipe:spawn `(,@GPG --dearmor))
(pipe:write-to sink-name
(logior O_WRONLY O_CREAT O_BINARY)
#o600)))
(for-each-p "Unpacking samples"
(lambda (name)
(dearmor (in-srcdir (string-append name "o.asc")) name))