diff --git a/ChangeLog b/ChangeLog index 20f1f8d5d6..154caca49d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,54 @@ +2006-05-09 Ulrich Drepper + + * 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 * 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 . @@ -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 + + +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 , 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 , 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 . @@ -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);