Little did I expect to see true segfault!
But that's exactly what happens when you invoke it via an invalid
use of execve.

With the patch below, I've exempted true and false from this sort of
abuse, but every program that calls set_program_name (argv[0]) will
suffer the same fate.

I haven't yet decided if/how to accommodate.
Maybe like this:
  set_program_name (argv[0] ? argv[0] : PROGRAM_NAME);

>From 4c9082a39618b5ef17f6cbb490d47a648c634da7 Mon Sep 17 00:00:00 2001
From: Jim Meyering <[email protected]>
Date: Sun, 15 Nov 2009 22:23:01 +0100
Subject: [PATCH] true, false: perform initialization only when argc == 2
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* src/true.c (main): There is no reason to examine argv[0],
call atexit, etc., in the usual case in which we're about to exit.
This has the side effect of making it so that these programs
no longer segfault when subjected to execve abuse.  Before this
change, this would segfault:
printf '%s\n' '#include <unistd.h>' 'int main(int c, char**v)' \
  '{ execve (v[1], 0, 0); }' > k.c && gcc k.c && ./a.out $PWD/true
Now it succeeds.  Reported by Tetsuo Handa and Bart Van Assche
via Ondřej Vašík in http://bugzilla.redhat.com/537684.
---
 src/true.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/true.c b/src/true.c
index f3e937f..d9d0118 100644
--- a/src/true.c
+++ b/src/true.c
@@ -54,18 +54,18 @@ Usage: %s [ignored command line arguments]\n\
 int
 main (int argc, char **argv)
 {
-  initialize_main (&argc, &argv);
-  set_program_name (argv[0]);
-  setlocale (LC_ALL, "");
-  bindtextdomain (PACKAGE, LOCALEDIR);
-  textdomain (PACKAGE);
-
-  atexit (close_stdout);
-
   /* Recognize --help or --version only if it's the only command-line
      argument.  */
   if (argc == 2)
     {
+      initialize_main (&argc, &argv);
+      set_program_name (argv[0]);
+      setlocale (LC_ALL, "");
+      bindtextdomain (PACKAGE, LOCALEDIR);
+      textdomain (PACKAGE);
+
+      atexit (close_stdout);
+
       if (STREQ (argv[1], "--help"))
         usage (EXIT_STATUS);

--
1.6.5.2.386.g2a326


Reply via email to