[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bugs when operating with closed file descriptors
From: |
Eric Blake |
Subject: |
bugs when operating with closed file descriptors |
Date: |
Thu, 20 Jul 2006 22:49:37 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
I'm still thinking about how best to patch this. I know gnulib provides the
stdio-safer module (and friends) that guarantee that stdio functions like fopen
don't reuse fd's 0, 1, or 2 (and hence that stdin, stdout, and stderr remain
closed if they started life closed). I also know that gnulib provides the
closeout module, which we should probably be using (and issue an error if any
output was attempted to stdout when it was already closed).
As a demonstration of the sorts of bugs currently in m4:
$ echo dnl | m4 -tdnl -oout
$ cat out
m4trace: -1- dnl
$ rm out
$ echo dnl | m4 -tdnl -oout >&-
$ cat out
$
Oops. When stdout is closed, out gets created with fd 1. Then in debug.c's
debug_set_file, we see if fileno(stdout) and fileno(debug) are the same file
(they are, since they are both fd 1), and close debug in favor of stdout.
Which means we lose all trace data, even though the above invocation is
perfectly legal (there was nothing written to stdout, so it shouldn't matter
whether stdout was closed).
$ echo hi | m4 >&-
$ echo $?
0
$
Oops. We should have issued an error to stdout stating we had a write error,
and exited with non-zero status.
$ m4 -tdnl 2>&- |tail
divert(-1)
define(f,`
')
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
define(`f',defn(`f')defn(`f'))
# f is now 2^20 bytes, large enough to overflow diversions into tmp file
divert(1)
f
divert
dnl()
undivert
bye
^D
stdin:27: m4: Warning: excess arguments to builtin `dnl' ignored
m4trace: -1- dnl
bye
$
Oops - the diversion spill opened fd 2, and messages to stderr got captured by
the tmp file, and undiverted into stdout, rather than discarded because stderr
was closed.
--
Eric Blake
- bugs when operating with closed file descriptors,
Eric Blake <=