about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog51
-rw-r--r--argp/Makefile6
-rw-r--r--argp/argp-help.c64
-rw-r--r--argp/bug-argp1.c26
-rw-r--r--elf/dl-dst.h15
-rw-r--r--elf/dl-load.c9
-rw-r--r--io/ftw.c2
-rw-r--r--locale/programs/ld-time.c13
-rw-r--r--nis/nss_nis/nis-service.c29
-rw-r--r--nptl/sysdeps/pthread/unwind-forcedunwind.c1
-rw-r--r--nss/nsswitch.c7
-rw-r--r--posix/getconf.c1
-rw-r--r--posix/wordexp.c7
-rw-r--r--stdlib/canonicalize.c4
-rw-r--r--sysdeps/posix/getaddrinfo.c11
-rw-r--r--sysdeps/unix/sysv/linux/ifaddrs.c8
16 files changed, 182 insertions, 72 deletions
diff --git a/ChangeLog b/ChangeLog
index 20f1f8d5d6..154caca49d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,54 @@
+2006-05-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* posix/wordexp.c (w_addword): Free word if realloc fails and it
+	was allocated here.  [Coverity CID 219]
+
+	* posix/getconf.c (print_all): Free confstr data after printing.
+	[Coverity CID 218]
+
+	* sysdeps/posix/getaddrinfo.c (gaih_inet): Free canon string if
+	list allocation fails.  [Coverity CID 215]
+
+	* nss/nsswitch.c (__nss_configure_lookup): Fix loop end condition.
+	[Coverity CID 213]
+
+	* argp/argp-help.c (hol_entry_cmp): Don't call canon_doc_option if
+	string is NULL.  [Coverity CID 212]
+	* argp/Makefile: Add rules to build and run bug-argp1.
+	* argp/bug-argp1.c: New file.
+
+	* io/ftw.c (ftw_dir): Use __rawmemchr instead of strchr to find
+	end of string.
+	* stdlib/canonicalize.c (__realpath): Likewise.
+
+	* locale/programs/ld-time.c (time_finish): Don't dereference NULL
+	pointer.  [Coverity CID 206]
+
+	* elf/dl-dst.h (DL_DST_REQUIRED): Be prepared for missing link map
+	in statically linked code.
+	* elf/dl-load.c (_dl_dst_substitute): When replacing ORIGIN in
+	statically built code, be prepared to have no link map.
+	[Coverity CID 205]
+
+	* argp/argp-help.c (fill_in_uparams): Handle STATE==NULL in
+	dgettext calls. [Coverity CID 204]
+
+	* argp/argp-help.c (struct uparams): Remove valid member.  Change
+	the one user.
+	(uparam_names): Reduce size.  Avoid relative relocations.
+	Moved to read-only segment.
+	(fill_in_uparams): Update for new layout.
+
+	* sysdeps/unix/sysv/linux/ifaddrs.c (getifaddrs): Parameter can be
+	assumed to always be != NULL. [Coverity CID 202]
+
+	* argp/argp-help.c (hol_entry_help): Remove some dead code
+	[Coverity CID 200].
+
+	* nis/nss_nis/nis-service.c (_nss_nis_getservbyport_r): Optimize
+	away a few more unconditional yperr2nss calls.
+	(_nss_nis_getservbyname_r): Likewise.
+
 2006-05-06  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/generic/ldsodefs.h: Remove support for non-core
diff --git a/argp/Makefile b/argp/Makefile
index a68ca1bee3..5ade517476 100644
--- a/argp/Makefile
+++ b/argp/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1997, 2002, 2003 Free Software Foundation, Inc.
+# Copyright (C) 1997, 2002, 2003, 2006 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -26,10 +26,12 @@ distribute	= argp-fmtstream.h argp-namefrob.h
 routines	= $(addprefix argp-, ba fmtstream fs-xinl help parse pv \
 				     pvh xinl eexst)
 
-tests		= argp-test tst-argp1
+tests		= argp-test tst-argp1 bug-argp1
 
 CFLAGS-argp-help.c = $(uses-callbacks) -fexceptions
 CFLAGS-argp-parse.c = $(uses-callbacks)
 CFLAGS-argp-fmtstream.c = -fexceptions
 
+bug-argp1-ARGS = -- --help
+
 include ../Rules
diff --git a/argp/argp-help.c b/argp/argp-help.c
index 4bc4d07b15..7ba621b735 100644
--- a/argp/argp-help.c
+++ b/argp/argp-help.c
@@ -1,5 +1,5 @@
 /* Hierarchial argument parsing help output
-   Copyright (C) 1995-2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1995-2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
@@ -128,40 +128,37 @@ struct uparams
   int header_col;
   int usage_indent;
   int rmargin;
-
-  int valid;			/* True when the values in here are valid.  */
 };
 
 /* This is a global variable, as user options are only ever read once.  */
 static struct uparams uparams = {
   DUP_ARGS, DUP_ARGS_NOTE,
   SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL,
-  USAGE_INDENT, RMARGIN,
-  0
+  USAGE_INDENT, RMARGIN
 };
 
 /* A particular uparam, and what the user name is.  */
 struct uparam_name
 {
-  const char *name;		/* User name.  */
-  int is_bool;			/* Whether it's `boolean'.  */
-  size_t uparams_offs;		/* Location of the (int) field in UPARAMS.  */
+  const char name[14];		/* User name.  */
+  bool is_bool;			/* Whether it's `boolean'.  */
+  uint8_t uparams_offs;		/* Location of the (int) field in UPARAMS.  */
 };
 
 /* The name-field mappings we know about.  */
 static const struct uparam_name uparam_names[] =
 {
-  { "dup-args",       1, offsetof (struct uparams, dup_args) },
-  { "dup-args-note",  1, offsetof (struct uparams, dup_args_note) },
-  { "short-opt-col",  0, offsetof (struct uparams, short_opt_col) },
-  { "long-opt-col",   0, offsetof (struct uparams, long_opt_col) },
-  { "doc-opt-col",    0, offsetof (struct uparams, doc_opt_col) },
-  { "opt-doc-col",    0, offsetof (struct uparams, opt_doc_col) },
-  { "header-col",     0, offsetof (struct uparams, header_col) },
-  { "usage-indent",   0, offsetof (struct uparams, usage_indent) },
-  { "rmargin",        0, offsetof (struct uparams, rmargin) },
-  { 0 }
+  { "dup-args",       true, offsetof (struct uparams, dup_args) },
+  { "dup-args-note",  true, offsetof (struct uparams, dup_args_note) },
+  { "short-opt-col",  false, offsetof (struct uparams, short_opt_col) },
+  { "long-opt-col",   false, offsetof (struct uparams, long_opt_col) },
+  { "doc-opt-col",    false, offsetof (struct uparams, doc_opt_col) },
+  { "opt-doc-col",    false, offsetof (struct uparams, opt_doc_col) },
+  { "header-col",     false, offsetof (struct uparams, header_col) },
+  { "usage-indent",   false, offsetof (struct uparams, usage_indent) },
+  { "rmargin",        false, offsetof (struct uparams, rmargin) }
 };
+#define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0]))
 
 /* Read user options from the environment, and fill in UPARAMS appropiately.  */
 static void
@@ -217,22 +214,27 @@ fill_in_uparams (const struct argp_state *state)
 		SKIPWS (arg);
 	      }
 
-	    for (un = uparam_names; un->name; un++)
+	    un = uparam_names;
+	    size_t u;
+	    for (u = 0; u < nuparam_names; ++un, ++u)
 	      if (strlen (un->name) == var_len
 		  && strncmp (var, un->name, var_len) == 0)
 		{
 		  if (unspec && !un->is_bool)
 		    __argp_failure (state, 0, 0,
-				    dgettext (state->root_argp->argp_domain, "\
+				    dgettext (state == NULL ? NULL
+					      : state->root_argp->argp_domain,
+					      "\
 %.*s: ARGP_HELP_FMT parameter requires a value"),
 				    (int) var_len, var);
 		  else
 		    *(int *)((char *)&uparams + un->uparams_offs) = val;
 		  break;
 		}
-	    if (! un->name)
+	    if (u == nuparam_names)
 	      __argp_failure (state, 0, 0,
-			      dgettext (state->root_argp->argp_domain, "\
+			      dgettext (state == NULL ? NULL
+					: state->root_argp->argp_domain, "\
 %.*s: Unknown ARGP_HELP_FMT parameter"),
 			      (int) var_len, var);
 
@@ -243,7 +245,8 @@ fill_in_uparams (const struct argp_state *state)
 	else if (*var)
 	  {
 	    __argp_failure (state, 0, 0,
-			    dgettext (state->root_argp->argp_domain,
+			    dgettext (state == NULL ? NULL
+				      : state->root_argp->argp_domain,
 				      "Garbage in ARGP_HELP_FMT: %s"), var);
 	    break;
 	  }
@@ -759,9 +762,9 @@ hol_entry_cmp (const struct hol_entry *entry1,
       const char *long2 = hol_entry_first_long (entry2);
 
       if (doc1)
-	doc1 = canon_doc_option (&long1);
+	doc1 = long1 != NULL && canon_doc_option (&long1);
       if (doc2)
-	doc2 = canon_doc_option (&long2);
+	doc2 = long2 != NULL && canon_doc_option (&long2);
 
       if (doc1 != doc2)
 	/* `documentation' options always follow normal options (or
@@ -1129,19 +1132,13 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
   else
     /* A real long option.  */
     {
-      int first_long_opt = 1;
-
       __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col);
       for (opt = real, num = entry->num; num > 0; opt++, num--)
 	if (opt->name && ovisible (opt))
 	  {
 	    comma (uparams.long_opt_col, &pest);
 	    __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;
+	    arg (real, "=%s", "[=%s]", state->root_argp->argp_domain, stream);
 	  }
     }
 
@@ -1555,8 +1552,7 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
   __flockfile (stream);
 #endif
 
-  if (! uparams.valid)
-    fill_in_uparams (state);
+  fill_in_uparams (state);
 
   fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
   if (! fs)
diff --git a/argp/bug-argp1.c b/argp/bug-argp1.c
new file mode 100644
index 0000000000..a28cf4b9c7
--- /dev/null
+++ b/argp/bug-argp1.c
@@ -0,0 +1,26 @@
+#include <argp.h>
+
+
+static const struct argp_option test_options[] =
+{
+  { NULL, 'a', NULL, OPTION_DOC, NULL },
+  { NULL, 'b', NULL, OPTION_DOC, NULL },
+  { NULL, 0, NULL, 0, NULL }
+};
+
+static struct argp test_argp =
+{
+  test_options
+};
+
+
+static int
+do_test (int argc, char *argv[])
+{
+  int i;
+  argp_parse (&test_argp, argc, argv, 0, &i, NULL);
+  return 0;
+}
+
+#define TEST_FUNCTION do_test (argc, argv)
+#include "../test-skeleton.c"
diff --git a/elf/dl-dst.h b/elf/dl-dst.h
index 42bd4185af..83d16bdb0e 100644
--- a/elf/dl-dst.h
+++ b/elf/dl-dst.h
@@ -1,5 +1,5 @@
 /* Handling of dynamic sring tokens.
-   Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999,2001,2002,2003,2004,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -50,6 +50,7 @@
 									      \
 	   First get the origin string if it is not available yet.	      \
 	   This can only happen for the map of the executable.  */	      \
+	DL_DST_REQ_STATIC						      \
 	if ((l)->l_origin == NULL)					      \
 	  {								      \
 	    assert ((l)->l_name[0] == '\0');				      \
@@ -66,6 +67,18 @@
 									      \
     __len; })
 
+#ifdef SHARED
+# define DL_DST_REQ_STATIC /* nothing */
+#else
+# define DL_DST_REQ_STATIC \
+  if ((l) == NULL)							      \
+    {									      \
+      const char *origin = _dl_get_origin ();				      \
+      origin_len = (origin && origin != (char *) -1 ? strlen (origin) : 0);   \
+    }									      \
+  else
+#endif
+
 #ifndef IS_IN_rtld
 # define _dl_get_origin GLRO(dl_get_origin)
 # define _dl_dst_substitute GLRO(dl_dst_substitute)
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 29fdfd8f19..01e1572f51 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -266,7 +266,14 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
 	  ++name;
 	  if ((len = is_dst (start, name, "ORIGIN", is_path,
 			     INTUSE(__libc_enable_secure))) != 0)
-	    repl = l->l_origin;
+	    {
+#ifndef SHARED
+	      if (l == NULL)
+		repl = _dl_get_origin ();
+	      else
+#endif
+		repl = l->l_origin;
+	    }
 	  else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0)
 	    repl = GLRO(dl_platform);
 	  else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0)
diff --git a/io/ftw.c b/io/ftw.c
index e96076a203..5c339a0624 100644
--- a/io/ftw.c
+++ b/io/ftw.c
@@ -526,7 +526,7 @@ fail:
 
   /* Next, update the `struct FTW' information.  */
   ++data->ftw.level;
-  startp = strchr (data->dirbuf, '\0');
+  startp = __rawmemchr (data->dirbuf, '\0');
   /* There always must be a directory name.  */
   assert (startp != data->dirbuf);
   if (startp[-1] != '/')
diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c
index 2d63275d3c..78aff7fee6 100644
--- a/locale/programs/ld-time.c
+++ b/locale/programs/ld-time.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
 
@@ -468,9 +468,14 @@ No definition for %s category found"), "LC_TIME"));
 	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end start */
 	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end end */
 	  time->era_entries[idx].wname = (uint32_t *) wstr + 1;
-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end name */
-	  *wstr = L'\0';
-	  time->era_entries[idx].wformat = (uint32_t *) wstr + 1;
+	  if (wstr != NULL)
+	    {
+	      wstr = wcschr (wstr + 1, L':');	/* end name */
+	      *wstr = L'\0';
+	      time->era_entries[idx].wformat = (uint32_t *) wstr + 1;
+	    }
+	  else
+	    time->era_entries[idx].wformat = NULL;
 	}
     }
 
diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c
index cb728335f9..c0e064d9a4 100644
--- a/nis/nss_nis/nis-service.c
+++ b/nis/nss_nis/nis-service.c
@@ -280,14 +280,13 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol,
 
   char *result;
   int int_len;
-  enum nss_status status = yperr2nss (yp_match (domain,
-						"services.byservicename", key,
-						keylen, &result, &int_len));
+  int status = yp_match (domain, "services.byservicename", key,
+			 keylen, &result, &int_len);
   size_t len = int_len;
 
   /* If we found the key, it's ok and parse the result. If not,
      fall through and parse the complete table. */
-  if (__builtin_expect (status == NSS_STATUS_SUCCESS, 1))
+  if (__builtin_expect (status == YPERR_SUCCESS, 1))
     {
       if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
 	{
@@ -317,7 +316,7 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol,
 
   /* Check if it is safe to rely on services.byservicename.  */
   if (_nsl_default_nss () & NSS_FLAG_SERVICES_AUTHORITATIVE)
-    return status;
+    return yperr2nss (status);
 
   struct ypall_callback ypcb;
   struct search_t req;
@@ -332,10 +331,10 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol,
   req.buflen = buflen;
   req.errnop = errnop;
   req.status = NSS_STATUS_NOTFOUND;
-  status = yperr2nss (yp_all (domain, "services.byname", &ypcb));
+  status = yp_all (domain, "services.byname", &ypcb);
 
-  if (status != NSS_STATUS_SUCCESS)
-    return status;
+  if (__builtin_expect (status != YPERR_SUCCESS, 0))
+    return yperr2nss (status);
 
   return req.status;
 }
@@ -362,14 +361,13 @@ _nss_nis_getservbyport_r (int port, const char *protocol,
 
       char *result;
       int int_len;
-      enum nss_status status = yperr2nss (yp_match (domain, "services.byname",
-						    key, keylen, &result,
-						    &int_len));
+      int status = yp_match (domain, "services.byname", key, keylen, &result,
+			     &int_len);
       size_t len = int_len;
 
       /* If we found the key, it's ok and parse the result. If not,
 	 fall through and parse the complete table. */
-      if (status == NSS_STATUS_SUCCESS)
+      if (__builtin_expect (status == YPERR_SUCCESS, 1))
 	{
 	  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
 	    {
@@ -414,11 +412,10 @@ _nss_nis_getservbyport_r (int port, const char *protocol,
   req.buflen = buflen;
   req.errnop = errnop;
   req.status = NSS_STATUS_NOTFOUND;
-  enum nss_status status = yperr2nss (yp_all (domain, "services.byname",
-					      &ypcb));
+  int status = yp_all (domain, "services.byname", &ypcb);
 
-  if (status != NSS_STATUS_SUCCESS)
-    return status;
+  if (__builtin_expect (status != YPERR_SUCCESS, 0))
+    return yperr2nss (status);
 
   return req.status;
 }
diff --git a/nptl/sysdeps/pthread/unwind-forcedunwind.c b/nptl/sysdeps/pthread/unwind-forcedunwind.c
index 2f1579586d..6792d719d3 100644
--- a/nptl/sysdeps/pthread/unwind-forcedunwind.c
+++ b/nptl/sysdeps/pthread/unwind-forcedunwind.c
@@ -31,6 +31,7 @@ static _Unwind_Reason_Code (*libgcc_s_forcedunwind)
 static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *);
 
 void
+__attribute_noinline__
 pthread_cancel_init (void)
 {
   void *resume, *personality, *forcedunwind, *getcfa;
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index 7e5e6e8164..21174dfbab 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005
+/* Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -70,6 +70,7 @@ static const struct
 #include "databases.def"
 #undef DEFINE_DATABASE
 };
+#define ndatabases (sizeof (databases) / sizeof (databases[0]))
 
 
 __libc_lock_define_initialized (static, lock)
@@ -211,7 +212,7 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
   service_user *new_db;
   size_t cnt;
 
-  for (cnt = 0; cnt < sizeof databases; ++cnt)
+  for (cnt = 0; cnt < ndatabases; ++cnt)
     {
       int cmp = strcmp (dbname, databases[cnt].name);
       if (cmp == 0)
@@ -223,7 +224,7 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
 	}
     }
 
-  if (cnt == sizeof databases)
+  if (cnt == ndatabases)
     {
       __set_errno (EINVAL);
       return -1;
diff --git a/posix/getconf.c b/posix/getconf.c
index 66e582e995..3c5ffe454c 100644
--- a/posix/getconf.c
+++ b/posix/getconf.c
@@ -981,6 +981,7 @@ print_all (const char *path)
         if (confstr (c->call_name, cvalue, clen) != clen)
           error (3, errno, "confstr");
         printf ("%.*s\n", (int) clen, cvalue);
+	free (cvalue);
         break;
     }
   }
diff --git a/posix/wordexp.c b/posix/wordexp.c
index 2eb58089c4..8dc07067c0 100644
--- a/posix/wordexp.c
+++ b/posix/wordexp.c
@@ -1,5 +1,5 @@
 /* POSIX.2 wordexp implementation.
-   Copyright (C) 1997-2002, 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1997-2002, 2003, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.
 
@@ -166,6 +166,7 @@ w_addword (wordexp_t *pwordexp, char *word)
   /* Add a word to the wordlist */
   size_t num_p;
   char **new_wordv;
+  bool allocated = false;
 
   /* Internally, NULL acts like "".  Convert NULLs to "" before
    * the caller sees them.
@@ -175,6 +176,7 @@ w_addword (wordexp_t *pwordexp, char *word)
       word = __strdup ("");
       if (word == NULL)
 	goto no_space;
+      allocated = true;
     }
 
   num_p = 2 + pwordexp->we_wordc + pwordexp->we_offs;
@@ -187,6 +189,9 @@ w_addword (wordexp_t *pwordexp, char *word)
       return 0;
     }
 
+  if (allocated)
+    free (word);
+
 no_space:
   return WRDE_NOSPACE;
 }
diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
index 9fc24b7d92..19808b50d6 100644
--- a/stdlib/canonicalize.c
+++ b/stdlib/canonicalize.c
@@ -1,5 +1,5 @@
 /* Return the canonical absolute name of a given file.
-   Copyright (C) 1996-2002, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1996-2002, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -91,7 +91,7 @@ __realpath (const char *name, char *resolved)
 	  rpath[0] = '\0';
 	  goto error;
 	}
-      dest = strchr (rpath, '\0');
+      dest = __rawmemchr (rpath, '\0');
     }
   else
     {
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index fc0928676d..224381c8db 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -1042,12 +1042,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	else
 	  socklen = sizeof (struct sockaddr_in);
 
+	struct addrinfo *pai_1st = pai;
 	for (st2 = st; st2 != NULL; st2 = st2->next)
 	  {
 	    struct addrinfo *ai;
 	    ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
 	    if (ai == NULL)
-	      return -EAI_MEMORY;
+	      {
+		free ((char *) canon);
+		return -EAI_MEMORY;
+	      }
 
 	    ai->ai_flags = req->ai_flags;
 	    ai->ai_family = family;
@@ -1065,6 +1069,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
 #endif /* _HAVE_SA_LEN */
 	    ai->ai_addr->sa_family = family;
 
+	    /* In case of an allocation error the list must be NULL
+	       terminated.  */
+	    ai->ai_next = NULL;
+
 	    if (family == AF_INET6)
 	      {
 		struct sockaddr_in6 *sin6p =
@@ -1088,7 +1096,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
 
 	    pai = &(ai->ai_next);
 	  }
-	*pai = NULL;
 
 	++*naddrs;
 
diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c
index f743f702f0..e6720f0ca2 100644
--- a/sysdeps/unix/sysv/linux/ifaddrs.c
+++ b/sysdeps/unix/sysv/linux/ifaddrs.c
@@ -1,5 +1,5 @@
 /* getifaddrs -- get names and addresses of all network interfaces
-   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -358,8 +358,7 @@ getifaddrs (struct ifaddrs **ifap)
 				ifa_data.  */
   int result = 0;
 
-  if (ifap)
-    *ifap = NULL;
+  *ifap = NULL;
 
   if (! __no_netlink_support && __netlink_open (&nh) < 0)
     {
@@ -840,8 +839,7 @@ getifaddrs (struct ifaddrs **ifap)
 	memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage));
     }
 
-  if (ifap != NULL)
-    *ifap = &ifas[0].ifa;
+  *ifap = &ifas[0].ifa;
 
  exit_free:
   __netlink_free_handle (&nh);