--- Begin Message ---
Subject: |
Mail delivery failed: returning message to sender |
Date: |
Tue, 02 Dec 2003 04:07:39 -0500 |
This message was created automatically by mail delivery software.
A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:
pipe to | /usr/lib/gnats/queue-pr -q
generated by address@hidden
(ultimately generated from address@hidden)
local delivery failed
------ This is a copy of the message, including all the headers. ------
Return-path: <address@hidden>
Received: from monty-python.gnu.org ([199.232.76.173])
by fencepost.gnu.org with esmtp (Exim 4.24)
id 1AR6VP-0004lB-55
for address@hidden; Tue, 02 Dec 2003 04:07:39 -0500
Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.24)
id 1AR7bf-0006YW-O0
for address@hidden; Tue, 02 Dec 2003 05:18:42 -0500
Received: from [213.182.8.6] (helo=mail.allgaeu.org)
by monty-python.gnu.org with esmtp (TLSv1:DES-CBC3-SHA:168)
(Exim 4.24)
id 1AR7be-0006XM-Pp
for address@hidden; Tue, 02 Dec 2003 05:18:11 -0500
Received: from kim.allgaeu.org (localhost [127.0.0.1])
by mail.allgaeu.org with ESMTP id hB29GdVQ002918
(version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=NO)
for <address@hidden>; Tue, 2 Dec 2003 10:16:40 +0100
X-Complaints-To: address@hidden
Received: (from address@hidden)
by kim.allgaeu.org with UUCP id hB29Gdpn002917
for address@hidden; Tue, 2 Dec 2003 10:16:39 +0100
Date: 2 Dec 2003 08:47:05 -0000
Message-ID: <address@hidden>
From: Ralph Schleicher <address@hidden>
To: address@hidden
Subject: call to argp_help generates a core dump
X-RCPT-Domain: gnu.org
X-Virus-Check: Yes
X-Spam-Check: Yes
X-Spam-Tests:
X-Spam-Status: No, hits=-0.2 required=5.0
tests=PATCH_CONTEXT_DIFF
version=2.55
X-Spam-Level:
X-Spam-Checker-Version: SpamAssassin 2.55 (1.174.2.19-2003-05-19-exp)
>Submitter-Id: net
>Originator: Ralph Schleicher
>Organization:
>
>Confidential: no
>Synopsis: sigsegv due to null-pointer dereferencing in glibc
>Severity: serious
>Priority: high
>Category: libc
>Class: sw-bug
>Release: libc-2.3.2
>Environment:
Host type: i686-pc-linux-gnu
System: Linux bravo 2.4.19 #1 SMP Fri Oct 18 16:57:39 CEST 2002 i686 unknown
Architecture: i686
Addons: linuxthreads
Build CFLAGS: -pipe -O2
Build CC: gcc
Compiler version: 3.2.2
Kernel headers: 2.4.19
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: yes
Build omitfp: no
Build bounded: no
Build static-nss: no
>Description:
A call to argp_help generates a core dump due to null-pointer
dereferencing
>How-To-Repeat:
Compile the following example program and run it with './argp-demo --help'.
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2003-12-02 09:35 CET by <address@hidden>.
# Source directory was `/home/rs/src/argp/lib/bug'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 101 -rw-r--r-- Makefile
# 1144 -rw-r--r-- argp-demo.c
# 4550 -rw-r--r-- prog.c
# 469 -rw-r--r-- prog.h
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
set `$dir/gettext --version 2>&1`
if test "$3" = GNU
then
gettext_dir=$dir
fi
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
shar_touch=touch
else
shar_touch=:
echo
$echo 'WARNING: not restoring timestamps. Consider getting and'
$echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh31221; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= Makefile ==============
if test -f 'Makefile' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'Makefile' '(file already exists)'
else
$echo 'x -' extracting 'Makefile' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
CC = gcc -g -Wall -W
CFLAGS = -D_GNU_SOURCE
X
argp-demo: argp-demo.c prog.c
X $(CC) $(CFLAGS) -o $@ $^
SHAR_EOF
$shar_touch -am 11292242103 'Makefile' &&
chmod 0644 'Makefile' ||
$echo 'restore of' 'Makefile' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'Makefile:' 'MD5 check failed'
96ec561384a6a486d1853a5df748c4eb Makefile
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Makefile'`"
test 101 -eq "$shar_count" ||
$echo 'Makefile:' 'original size' '101,' 'current size' "$shar_count!"
fi
fi
# ============= argp-demo.c ==============
if test -f 'argp-demo.c' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'argp-demo.c' '(file already exists)'
else
$echo 'x -' extracting 'argp-demo.c' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'argp-demo.c' &&
#include <stdlib.h>
#include <string.h>
#include <argp.h>
#include "prog.h"
X
#define PACKAGE "argp-demo"
#define VERSION "1.0"
X
static char *log_file = PACKAGE ".log";
static char *run_file = PACKAGE ".pid";
X
static struct argp_option options[] =
X {
X {"log-file", 'l', "FILE", 0, "Write status messages to file FILE", 0},
X {"run-file", 'p', "FILE", 0, "Save runtime information in file FILE", 0},
X {NULL, 0, NULL, 0, NULL, 0},
X };
X
X
static error_t
parser (int key, char *arg, struct argp_state *state __attribute__ ((unused)))
{
X switch (key)
X {
X case 'l':
X log_file = arg;
X return 0;
X
X case 'r':
X run_file = arg;
X return 0;
X }
X
X return ARGP_ERR_UNKNOWN;
}
X
X
int
main (int argc, char *argv[])
{
X struct argp argp = {options, parser};
X int i;
X
X package_name = PACKAGE;
X package_version = VERSION;
X package_string = PACKAGE " " VERSION;
X package_address = "address@hidden";
X
X i = setup_program (argc, argv, &argp);
X
X printf ("log-file = %s\n", log_file);
X printf ("run-file = %s\n", run_file);
X
X for (; i < argc; ++i)
X printf ("%d: %s\n", i, argv[i]);
X
X exit (EXIT_SUCCESS);
}
SHAR_EOF
$shar_touch -am 11292239103 'argp-demo.c' &&
chmod 0644 'argp-demo.c' ||
$echo 'restore of' 'argp-demo.c' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'argp-demo.c:' 'MD5 check failed'
eb716876eda57a054a1d9cab43aa2118 argp-demo.c
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'argp-demo.c'`"
test 1144 -eq "$shar_count" ||
$echo 'argp-demo.c:' 'original size' '1144,' 'current size' "$shar_count!"
fi
fi
# ============= prog.c ==============
if test -f 'prog.c' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'prog.c' '(file already exists)'
else
$echo 'x -' extracting 'prog.c' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'prog.c' &&
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <argp.h>
#include "prog.h"
X
/* Package variables. */
char *package_name;
char *package_version;
char *package_string;
char *package_copying;
char *package_address;
X
/* Program invocation name. */
char *invocation_name;
X
/* Program name sans directory. */
char *program_name;
X
/* Standard options. */
struct opt
X {
X /* Non-zero means display help text. */
X int help;
X
X /* Non-zero means display usage message. */
X int usage;
X
X /* Non-zero means display version information. */
X int version;
X };
X
enum
X {
X OPT_HELP = 256,
X OPT_USAGE,
X OPT_VERSION
X };
X
static struct argp_option opt_options[] =
X {
X {"help", OPT_HELP, NULL, 0, "Display this help and exit", -1},
X {"usage", OPT_USAGE, NULL, 0, "Display usage message and exit", -1},
X {"version", OPT_VERSION, NULL, 0, "Display version information and exit",
-1},
X {NULL, 0, NULL, 0, NULL, 0},
X };
X
/* Forward declarations. */
static char *base_name (const char *name);
X
X
/* Parser for standard options. */
static error_t
opt_parser (int key, char *arg __attribute__ ((unused)), struct argp_state
*state)
{
X struct opt *opt = state->input;
X
X switch (key)
X {
X case OPT_HELP:
X opt->help = 1;
X return 0;
X
X case OPT_USAGE:
X opt->usage = 1;
X return 0;
X
X case OPT_VERSION:
X opt->version = 1;
X return 0;
X }
X
X return ARGP_ERR_UNKNOWN;
}
X
X
/* Initialize program. */
int
setup_program (int argc, char **argv, void *argp)
{
X struct argp common, parent;
X struct argp_child child[3];
X struct opt opt;
X int err, ind;
X int outp;
X
X invocation_name = argv[0];
X if (*invocation_name == 0)
X abort ();
X
X program_name = base_name (invocation_name);
X if (*program_name == 0)
X abort ();
X
X common.options = opt_options;
X common.parser = opt_parser;
X common.args_doc = NULL;
X common.doc = NULL;
X common.children = NULL;
X common.help_filter = NULL;
X common.argp_domain = NULL;
X
X parent.options = NULL;
X parent.parser = NULL;
X parent.args_doc = NULL;
X parent.doc = NULL;
X parent.children = child;
X parent.help_filter = NULL;
X parent.argp_domain = NULL;
X
X child[0].argp = &common;
X child[0].flags = 0;
X child[0].header = NULL;
X child[0].group = -1;
X
X child[1].argp = argp;
X child[1].flags = 0;
X child[1].header = NULL;
X child[1].group = 0;
X
X child[2].argp = NULL;
X child[2].flags = 0;
X child[2].header = NULL;
X child[2].group = 0;
X
X argp = &parent;
X
X /* Default values. */
X opt.help = 0;
X opt.usage = 0;
X opt.version = 0;
X
X err = argp_parse (argp, argc, argv, ARGP_SILENT, &ind, &opt);
X switch (err)
X {
X case 0:
X
X if (opt.version)
X {
X if (package_name != NULL)
X {
X fputs (package_name, stdout);
X
X if (package_version != NULL)
X {
X fputc (' ', stdout);
X fputs (package_version, stdout);
X }
X
X if (package_string != NULL)
X {
X fputc (' ', stdout);
X fputc ('(', stdout);
X fputs (package_string, stdout);
X fputc (')', stdout);
X }
X
X if (package_copying != NULL)
X {
X fputc ('\n', stdout);
X fputc ('\n', stdout);
X fputs (package_copying, stdout);
X }
X
X fputc ('\n', stdout);
X outp = 1;
X }
X else
X {
X fprintf (stderr, "%s: %s\n", program_name,
X "No version information available");
X }
X }
X
X if (opt.usage)
X {
X if (outp)
X fputc ('\n', stdout);
X
X argp_help (argp, stdout, ARGP_HELP_USAGE, program_name);
X outp = 1;
X }
X
X if (opt.help)
X {
X unsigned int flags;
X
X flags = opt.usage ? 0 : ARGP_HELP_SHORT_USAGE;
X flags |= (ARGP_HELP_LONG | ARGP_HELP_DOC);
X
X if (outp)
X fputc ('\n', stdout);
X
X argp_help (argp, stdout, flags, program_name);
X outp = 1;
X
X if (package_address != NULL)
X {
X fputc ('\n', stdout);
X fputs ("Report bugs to <", stdout);
X fputs (package_address, stdout);
X fputs (">.\n", stdout);
X }
X }
X
X if (opt.version || opt.usage || opt.help)
X exit (EXIT_SUCCESS);
X
X return ind;
X
X case EINVAL:
X
X fprintf (stderr, "%s: Unrecognized option '%s'\n",
X program_name, argv[optind]);
X
X fprintf (stderr, "Try '%s --help' for more information\n",
X invocation_name);
X
X exit (EXIT_FAILURE);
X
X default:
X
X fprintf (stderr, "%s: %s\n",
X program_name, strerror (err));
X
X exit (EXIT_FAILURE);
X }
}
X
X
/* Return base name. */
static char *
base_name (const char *name)
{
X char *tem;
X
X tem = strrchr (name, '/');
X if (tem == NULL)
X return (char *) name;
X else
X return tem + 1;
}
SHAR_EOF
$shar_touch -am 11292242103 'prog.c' &&
chmod 0644 'prog.c' ||
$echo 'restore of' 'prog.c' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'prog.c:' 'MD5 check failed'
9b09ed7e84339ff55479cb961ed6ecce prog.c
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'prog.c'`"
test 4550 -eq "$shar_count" ||
$echo 'prog.c:' 'original size' '4550,' 'current size' "$shar_count!"
fi
fi
# ============= prog.h ==============
if test -f 'prog.h' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'prog.h' '(file already exists)'
else
$echo 'x -' extracting 'prog.h' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'prog.h' &&
#ifndef LOGGER_PROG_H
#define LOGGER_PROG_H
X
/* User variables. */
extern char *package_name;
extern char *package_version;
extern char *package_string;
extern char *package_address;
extern char *package_copying;
X
/* Program invocation name. */
extern char *invocation_name;
X
/* Program name sans directory. */
extern char *program_name;
X
/* Initialize program. */
extern int setup_program (int __argc, char **__argv, void *__argp);
X
#endif /* not LOGGER_PROG_H */
SHAR_EOF
$shar_touch -am 11272001103 'prog.h' &&
chmod 0644 'prog.h' ||
$echo 'restore of' 'prog.h' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'prog.h:' 'MD5 check failed'
2afe0e271f4f062c98a4b99ac7538d90 prog.h
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'prog.h'`"
test 469 -eq "$shar_count" ||
$echo 'prog.h:' 'original size' '469,' 'current size' "$shar_count!"
fi
fi
rm -fr _sh31221
exit 0
>Fix:
Apply the following patch. Here is the associated ChangeLog entry:
2003-11-29 Ralph Schleicher <address@hidden>
* argp/argp-help.c (hol_entry_help, hol_help, fill_in_uparams):
Check if state is non-null before accessing a structure member.
* argp/argp-help.c (filter_doc): Check if argp is non-null before
accessing a structure member.
diff -c2d glibc-2.3.2/argp/argp-help.c.orig glibc-2.3.2/argp/argp-help.c
*** glibc-2.3.2/argp/argp-help.c.orig Thu Nov 27 21:17:02 2003
--- glibc-2.3.2/argp/argp-help.c Thu Nov 27 22:23:35 2003
***************
*** 156,159 ****
--- 156,160 ----
{
const char *var = getenv ("ARGP_HELP_FMT");
+ const char *domain = state ? state->root_argp->argp_domain : NULL;
#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0);
***************
*** 211,215 ****
if (unspec && !un->is_bool)
__argp_failure (state, 0, 0,
! dgettext (state->root_argp->argp_domain, "\
%.*s: ARGP_HELP_FMT parameter requires a value"),
(int) var_len, var);
--- 212,216 ----
if (unspec && !un->is_bool)
__argp_failure (state, 0, 0,
! dgettext (domain, "\
%.*s: ARGP_HELP_FMT parameter requires a value"),
(int) var_len, var);
***************
*** 220,224 ****
if (! un->name)
__argp_failure (state, 0, 0,
! dgettext (state->root_argp->argp_domain, "\
%.*s: Unknown ARGP_HELP_FMT parameter"),
(int) var_len, var);
--- 221,225 ----
if (! un->name)
__argp_failure (state, 0, 0,
! dgettext (domain, "\
%.*s: Unknown ARGP_HELP_FMT parameter"),
(int) var_len, var);
***************
*** 231,235 ****
{
__argp_failure (state, 0, 0,
! dgettext (state->root_argp->argp_domain,
"Garbage in ARGP_HELP_FMT: %s"), var);
break;
--- 232,236 ----
{
__argp_failure (state, 0, 0,
! dgettext (domain,
"Garbage in ARGP_HELP_FMT: %s"), var);
break;
***************
*** 963,967 ****
const struct argp_state *state)
{
! if (argp->help_filter)
/* We must apply a user filter to this output. */
{
--- 964,968 ----
const struct argp_state *state)
{
! if (argp && argp->help_filter)
/* We must apply a user filter to this output. */
{
***************
*** 1060,1063 ****
--- 1061,1065 ----
share with helper functions. */
struct pentry_state pest = { entry, stream, hhstate, 1, state };
+ const char *domain = state ? state->root_argp->argp_domain : NULL;
if (! odoc (real))
***************
*** 1081,1085 ****
__argp_fmtstream_putc (stream, *so);
if (!have_long_opt || uparams.dup_args)
! arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream);
else if (real->arg)
hhstate->suppressed_dup_arg = 1;
--- 1083,1087 ----
__argp_fmtstream_putc (stream, *so);
if (!have_long_opt || uparams.dup_args)
! arg (real, " %s", "[%s]", domain, stream);
else if (real->arg)
hhstate->suppressed_dup_arg = 1;
***************
*** 1100,1106 ****
have been done on the original; but documentation options
should be pretty rare anyway... */
! __argp_fmtstream_puts (stream,
! dgettext (state->root_argp->argp_domain,
! opt->name));
}
}
--- 1102,1106 ----
have been done on the original; but documentation options
should be pretty rare anyway... */
! __argp_fmtstream_puts (stream, dgettext (domain, opt->name));
}
}
***************
*** 1117,1122 ****
__argp_fmtstream_printf (stream, "--%s", opt->name);
if (first_long_opt || uparams.dup_args)
! arg (real, "=%s", "[=%s]", state->root_argp->argp_domain,
! stream);
else if (real->arg)
hhstate->suppressed_dup_arg = 1;
--- 1117,1121 ----
__argp_fmtstream_printf (stream, "--%s", opt->name);
if (first_long_opt || uparams.dup_args)
! arg (real, "=%s", "[=%s]", domain, stream);
else if (real->arg)
hhstate->suppressed_dup_arg = 1;
***************
*** 1139,1144 ****
else
{
! const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain,
! real->doc) : 0;
const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
if (fstr && *fstr)
--- 1138,1142 ----
else
{
! const char *tstr = real->doc ? dgettext (domain, real->doc) : 0;
const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
if (fstr && *fstr)
***************
*** 1181,1184 ****
--- 1179,1183 ----
struct hol_entry *entry;
struct hol_help_state hhstate = { 0, 0, 0 };
+ const char *domain = state ? state->root_argp->argp_domain : NULL;
for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
***************
*** 1187,1191 ****
if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
{
! const char *tstr = dgettext (state->root_argp->argp_domain, "\
Mandatory or optional arguments to long options are also mandatory or \
optional for any corresponding short options.");
--- 1186,1190 ----
if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
{
! const char *tstr = dgettext (domain, "\
Mandatory or optional arguments to long options are also mandatory or \
optional for any corresponding short options.");
--- End Message ---