bug-m4
[Top][All Lists]
Advanced

[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







reply via email to

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