bug-bash
[Top][All Lists]
Advanced

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

read -N 1 </dev/zero runs forever


From: John Passaro
Subject: read -N 1 </dev/zero runs forever
Date: Mon, 4 Feb 2019 11:45:17 -0500 (EST)

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin17.5.0
Compiler: clang
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='darwin17.5.0' -DCONF_MACHTYPE='x86_64-apple-darwin17.5.0' 
-DCONF_VENDOR='apple' -DLOCALEDIR='/usr/local/Cellar/bash/4.4.23/share/locale' 
-DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -DMACOSX   -I.  -I. -I./include 
-I./lib -I./lib/intl -I/private/tmp/bash-20180602-817-1lkxzgr/bash-4.4/lib/intl 
 -DSSH_SOURCE_BASHRC -Wno-parentheses -Wno-format-security
uname output: Darwin pop-jpas-mbpr-4.local 17.7.0 Darwin Kernel Version 17.7.0: 
Fri Nov  2 20:43:16 PDT 2018; root:xnu-4570.71.17~1/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin17.5.0

Bash Version: 4.4
Patch Level: 23
Release Status: release

Description:
        The `read` builtin skips null characters and does not count
        them toward the limit specified by -n/-N. This leads to
        surprising behavior with /dev/zero: read -N 1 </dev/zero
        never terminates!

        This is obviously a corner case but it violates what ought
        to be a safe user assumption that specifying -N prevents
        read from running for too long.

Repeat-By:
        $ tr \\0 a </dev/zero | read -N # terminates immediately
        $ tr \\0 \\0 </dev/zero | read -N # runs forever

        or in the absence of /dev/zero:
        $ while true ; do echo -n a ; done | read -N 1 # terminates
        $ while true ; do echo -n a ; done | tr a \\0 | read -N 1 # runs forever

Fix:
        I propose to count nulls toward nchars.

        In the patch I replaced a `continue` with a `goto` that should
        result in equivalent behavior except for the case I'm raising
        here.  The only other place that the input char doesn't count
        toward nchars is when it's a backslash or a newline just after a
        backslash, and -r is not specified. I see no need to disrupt
        that behavior, but the case could be made; I leave it to the
        maintainers.

diff --git a/builtins/read.def b/builtins/read.def
index b57c8c398e18..5713766e4c3a 100644
--- a/builtins/read.def
+++ b/builtins/read.def
@@ -672,7 +672,7 @@ read_builtin (list)
        break;
 
       if (c == '\0' && delim != '\0')
-       continue;               /* skip NUL bytes in input */
+       goto increment_byte_count;              /* skip NUL bytes in input */
 
       if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == 
CTLNUL))
        {
@@ -713,6 +713,7 @@ add_char:
        }
 #endif
 
+increment_byte_count:
       nr++;
 
       if (nchars > 0 && nr >= nchars)
diff --git a/tests/read.right b/tests/read.right
index 73cb7042fbca..649c78a568c5 100644
--- a/tests/read.right
+++ b/tests/read.right
@@ -45,6 +45,7 @@ abcde
 abc
 ab
 abc
+ac
 #
 while read -u 3 var
 do
diff --git a/tests/read3.sub b/tests/read3.sub
index af41e3f27930..02334fdad6d2 100644
--- a/tests/read3.sub
+++ b/tests/read3.sub
@@ -20,5 +20,11 @@ echo abc | {
        echo $foo
 }
 
+# does not consume too many characters
+echo abcde | tr b '\0' | {
+       read -N 3 foo
+       echo $foo
+}
+
 read -n 1 < $0
 echo "$REPLY"




reply via email to

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