diff options
author | Martijn van Duren <martijn@cvs.openbsd.org> | 2021-08-11 15:13:47 +0000 |
---|---|---|
committer | Martijn van Duren <martijn@cvs.openbsd.org> | 2021-08-11 15:13:47 +0000 |
commit | 6dcd911f8f560797d1b0ab31ae6b534bbe480bba (patch) | |
tree | d8644a0782c613dddd810c1fe56353efd2f59b0b /lib | |
parent | 2d49304fff5cb7247f09a85b1589b54210155e48 (diff) |
Only enter the sig_no switch if we actually return from read(2) with
errno == EINTR. There was a race here where read(2) can return with a
different errno, but the signal handler enters between the read return and
the switch, which could result in handling a signal, while we should be
handling the error.
This fix assumes that signal handlers don't clobber our errno, but doing
that would open a whole other can of worms.
OK schwarze@, millert@
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libedit/read.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/lib/libedit/read.c b/lib/libedit/read.c index 754d898a222..7900193aecc 100644 --- a/lib/libedit/read.c +++ b/lib/libedit/read.c @@ -1,4 +1,4 @@ -/* $OpenBSD: read.c,v 1.46 2021/08/10 14:28:10 schwarze Exp $ */ +/* $OpenBSD: read.c,v 1.47 2021/08/11 15:13:46 martijn Exp $ */ /* $NetBSD: read.c,v 1.100 2016/05/24 19:31:27 christos Exp $ */ /*- @@ -240,15 +240,17 @@ read_char(EditLine *el, wchar_t *cp) el->el_signal->sig_no = 0; while ((num_read = read(el->el_infd, cbuf + cbp, 1)) == -1) { int e = errno; - switch (el->el_signal->sig_no) { - case SIGCONT: - el_set(el, EL_REFRESH); - /*FALLTHROUGH*/ - case SIGWINCH: - sig_set(el); - goto again; - default: - break; + if (errno == EINTR) { + switch (el->el_signal->sig_no) { + case SIGCONT: + el_set(el, EL_REFRESH); + /*FALLTHROUGH*/ + case SIGWINCH: + sig_set(el); + goto again; + default: + break; + } } if (!tried && read__fixio(el->el_infd, e) == 0) { errno = save_errno; |