Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 583711 Details for
Bug 797096
glibc: unbound alloca use in glob_in_dir
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Patch part#1
glibc-rh797096-1.patch (text/plain), 18.69 KB, created by
Jeff Law
on 2012-05-11 03:46:41 UTC
(
hide
)
Description:
Patch part#1
Filename:
MIME Type:
Creator:
Jeff Law
Created:
2012-05-11 03:46:41 UTC
Size:
18.69 KB
patch
obsolete
>diff -rup a/include/alloca.h b/include/alloca.h >--- a/include/alloca.h 2012-02-28 12:28:02.463882556 -0700 >+++ b/include/alloca.h 2012-02-28 12:38:38.758539767 -0700 >@@ -48,15 +48,24 @@ extern int __libc_alloca_cutoff (size_t > > #if defined stackinfo_get_sp && defined stackinfo_sub_sp > # define alloca_account(size, avar) \ >- ({ void *old__ = stackinfo_get_sp (); \ >- void *m__ = __alloca (size); \ >- avar += stackinfo_sub_sp (old__); \ >+ ({ void *old__ = stackinfo_get_sp (); \ >+ void *m__ = __alloca (size); \ >+ avar += stackinfo_sub_sp (old__); \ >+ m__; }) >+# define extend_alloca_account(buf, len, newlen, avar) \ >+ ({ void *old__ = stackinfo_get_sp (); \ >+ void *m__ = extend_alloca (buf, len, newlen); \ >+ avar += stackinfo_sub_sp (old__); \ > m__; }) > #else > # define alloca_account(size, avar) \ >- ({ size_t s__ = (size); \ >- avar += s__; \ >+ ({ size_t s__ = (size); \ >+ avar += s__; \ > __alloca (s__); }) >+# define extend_alloca_account(buf, len, newlen, avar) \ >+ ({ size_t s__ = (newlen); \ >+ avar += s__; \ >+ extend_alloca (buf, len, s__); }) > #endif > > #endif >Only in b/include: alloca.h.orig >diff -rup a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c >--- a/sysdeps/posix/getaddrinfo.c 2012-02-28 12:28:02.759880989 -0700 >+++ b/sysdeps/posix/getaddrinfo.c 2012-02-28 13:04:23.585309134 -0700 >@@ -382,6 +382,7 @@ gaih_inet (const char *name, const struc > bool got_ipv6 = false; > const char *canon = NULL; > const char *orig_name = name; >+ size_t alloca_used = 0; > > if (req->ai_protocol || req->ai_socktype) > { >@@ -414,7 +415,7 @@ gaih_inet (const char *name, const struc > if (tp->name[0]) > { > st = (struct gaih_servtuple *) >- __alloca (sizeof (struct gaih_servtuple)); >+ alloca_account (sizeof (struct gaih_servtuple), alloca_used); > > if ((rc = gaih_inet_serv (service->name, tp, req, st))) > return rc; >@@ -438,7 +439,8 @@ gaih_inet (const char *name, const struc > continue; > > newp = (struct gaih_servtuple *) >- __alloca (sizeof (struct gaih_servtuple)); >+ alloca_account (sizeof (struct gaih_servtuple), >+ alloca_used); > > if ((rc = gaih_inet_serv (service->name, tp, req, newp))) > { >@@ -466,7 +468,7 @@ gaih_inet (const char *name, const struc > > if (req->ai_socktype || req->ai_protocol) > { >- st = __alloca (sizeof (struct gaih_servtuple)); >+ st = alloca_account (sizeof (struct gaih_servtuple), alloca_used); > st->next = NULL; > st->socktype = tp->socktype; > st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) >@@ -482,7 +484,8 @@ gaih_inet (const char *name, const struc > { > struct gaih_servtuple *newp; > >- newp = __alloca (sizeof (struct gaih_servtuple)); >+ newp = alloca_account (sizeof (struct gaih_servtuple), >+ alloca_used); > newp->next = NULL; > newp->socktype = tp->socktype; > newp->protocol = tp->protocol; >@@ -494,10 +497,17 @@ gaih_inet (const char *name, const struc > } > } > >+ bool malloc_name = false; >+ bool malloc_addrmem = false; >+ struct gaih_addrtuple *addrmem = NULL; >+ bool malloc_canonbuf = false; >+ char *canonbuf = NULL; >+ bool malloc_tmpbuf = false; >+ char *tmpbuf = NULL; >+ int result = 0; > if (name != NULL) > { >- at = __alloca (sizeof (struct gaih_addrtuple)); >- >+ at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); > at->family = AF_UNSPEC; > at->scopeid = 0; > at->next = NULL; >@@ -515,6 +525,7 @@ gaih_inet (const char *name, const struc > rc = __idna_to_ascii_lz (name, &p, idn_flags); > if (rc != IDNA_SUCCESS) > { >+ /* No need to jump to free_and_return here. */ > if (rc == IDNA_MALLOC_ERROR) > return -EAI_MEMORY; > if (rc == IDNA_DLOPEN_ERROR) >@@ -524,10 +535,7 @@ gaih_inet (const char *name, const struc > /* In case the output string is the same as the input string > no new string has been allocated. */ > if (p != name) >- { >- name = strdupa (p); >- free (p); >- } >+ malloc_name = true; > } > #endif > >@@ -544,23 +552,59 @@ gaih_inet (const char *name, const struc > at->family = AF_INET6; > } > else >- return -EAI_ADDRFAMILY; >+ { >+ result = -EAI_ADDRFAMILY; >+ goto free_and_return; >+ } > > if (req->ai_flags & AI_CANONNAME) > canon = name; > } > else if (at->family == AF_UNSPEC) > { >- char *namebuf = (char *) name; > char *scope_delim = strchr (name, SCOPE_DELIMITER); >+ int e; > >- if (__builtin_expect (scope_delim != NULL, 0)) >- { >- namebuf = alloca (scope_delim - name + 1); >- *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0'; >- } >+ { >+ bool malloc_namebuf = false; >+ char *namebuf = (char *) name; > >- if (inet_pton (AF_INET6, namebuf, at->addr) > 0) >+ if (__builtin_expect (scope_delim != NULL, 0)) >+ { >+ if (malloc_name) >+ *scope_delim = '\0'; >+ else >+ { >+ if (__libc_use_alloca (alloca_used >+ + scope_delim - name + 1)) >+ { >+ namebuf = alloca_account (scope_delim - name + 1, >+ alloca_used); >+ *((char *) __mempcpy (namebuf, name, >+ scope_delim - name)) = '\0'; >+ } >+ else >+ { >+ namebuf = strndup (name, scope_delim - name); >+ if (namebuf == NULL) >+ { >+ assert (!malloc_name); >+ return -EAI_MEMORY; >+ } >+ malloc_namebuf = true; >+ } >+ } >+ } >+ >+ e = inet_pton (AF_INET6, namebuf, at->addr); >+ >+ if (malloc_namebuf) >+ free (namebuf); >+ else if (scope_delim != NULL && malloc_name) >+ /* Undo what we did above. */ >+ *scope_delim = SCOPE_DELIMITER; >+ } >+ if (e > 0) > { > if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) > at->family = AF_INET6; >@@ -571,7 +615,10 @@ gaih_inet (const char *name, const struc > at->family = AF_INET; > } > else >- return -EAI_ADDRFAMILY; >+ { >+ result = -EAI_ADDRFAMILY; >+ goto free_and_return; >+ } > > if (scope_delim != NULL) > { >@@ -593,7 +640,10 @@ gaih_inet (const char *name, const struc > at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end, > 10); > if (*end != '\0') >- return GAIH_OKIFUNSPEC | -EAI_NONAME; >+ { >+ result = GAIH_OKIFUNSPEC | -EAI_NONAME; >+ goto free_and_return; >+ } > } > } > >@@ -622,59 +672,80 @@ gaih_inet (const char *name, const struc > { > int family = req->ai_family; > size_t tmpbuflen = 512; >- char *tmpbuf = alloca (tmpbuflen); >+ assert (tmpbuf == NULL); >+ tmpbuf = alloca_account (tmpbuflen, alloca_used); > int rc; > struct hostent th; > struct hostent *h; > int herrno; > >- simple_again: > while (1) > { >- rc = __gethostbyname2_r (name, family, &th, tmpbuf, >+ rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf, > tmpbuflen, &h, &herrno); > if (rc != ERANGE || herrno != NETDB_INTERNAL) > break; >- tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); >+ >+ if (!malloc_tmpbuf >+ && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) >+ tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, >+ 2 * tmpbuflen, >+ alloca_used); >+ else >+ { >+ char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, >+ 2 * tmpbuflen); >+ if (newp == NULL) >+ { >+ result = -EAI_MEMORY; >+ goto free_and_return; >+ } >+ tmpbuf = newp; >+ malloc_tmpbuf = true; >+ tmpbuflen = 2 * tmpbuflen; >+ } > } > > if (rc == 0) > { >- if (h == NULL) >+ if (h != NULL) > { >- if (req->ai_family == AF_INET6 >- && (req->ai_flags & AI_V4MAPPED) >- && family == AF_INET6) >+ int i; >+ /* We found data, count the number of addresses. */ >+ for (i = 0; h->h_addr_list[i]; ++i) >+ ; >+ if (i > 0 && *pat != NULL) >+ --i; >+ >+ if (__libc_use_alloca (alloca_used >+ + i * sizeof (struct gaih_addrtuple))) >+ addrmem = alloca_account (i * sizeof (struct gaih_addrtuple), >+ alloca_used); >+ else >+ { >+ addrmem = malloc (i >+ * sizeof (struct gaih_addrtuple)); >+ if (addrmem == NULL) > { >- /* Try again, this time looking for IPv4 >- addresses. */ >- family = AF_INET; >- goto simple_again; >+ result = -EAI_MEMORY; >+ goto free_and_return; > } >+ malloc_addrmem = true; > } >- else >- { >- /* We found data, now convert it into the list. */ >- for (int i = 0; h->h_addr_list[i]; ++i) >+ >+ /* Now convert it into the list. */ >+ struct gaih_addrtuple *addrfree = addrmem; >+ for (i = 0; h->h_addr_list[i]; ++i) > { > if (*pat == NULL) > { >- *pat = __alloca (sizeof (struct gaih_addrtuple)); >+ *pat = addrfree++; > (*pat)->scopeid = 0; > } > (*pat)->next = NULL; >- (*pat)->family = req->ai_family; >- if (family == req->ai_family) >+ (*pat)->family = AF_INET; > memcpy ((*pat)->addr, h->h_addr_list[i], > h->h_length); >- else >- { >- uint32_t *addr = (uint32_t *) (*pat)->addr; >- addr[3] = *(uint32_t *) h->h_addr_list[i]; >- addr[2] = htonl (0xffff); >- addr[1] = 0; >- addr[0] = 0; >- } > pat = &((*pat)->next); > } > } >@@ -684,15 +755,16 @@ gaih_inet (const char *name, const struc > if (herrno == NETDB_INTERNAL) > { > __set_h_errno (herrno); >- return -EAI_SYSTEM; >- } >- if (herrno == TRY_AGAIN) >- { >- return -EAI_AGAIN; >+ result = -EAI_SYSTEM; > } >+ else if (herrno == TRY_AGAIN) >+ result = -EAI_AGAIN; >+ else > /* We made requests but they turned out no data. > The name is known, though. */ >- return GAIH_OKIFUNSPEC | -EAI_NODATA; >+ result = GAIH_OKIFUNSPEC | -EAI_NODATA; >+ >+ goto free_and_return; > } > > goto process_list; >@@ -715,21 +787,56 @@ gaih_inet (const char *name, const struc > bool added_canon = (req->ai_flags & AI_CANONNAME) == 0; > char *addrs = air->addrs; > >+ if (__libc_use_alloca (alloca_used >+ + air->naddrs * sizeof (struct gaih_addrtuple))) >+ addrmem = alloca_account (air->naddrs >+ * sizeof (struct gaih_addrtuple), >+ alloca_used); >+ else >+ { >+ addrmem = malloc (air->naddrs >+ * sizeof (struct gaih_addrtuple)); >+ if (addrmem == NULL) >+ { >+ result = -EAI_MEMORY; >+ goto free_and_return; >+ } >+ malloc_addrmem = true; >+ } >+ >+ struct gaih_addrtuple *addrfree = addrmem; > for (int i = 0; i < air->naddrs; ++i) > { > socklen_t size = (air->family[i] == AF_INET > ? INADDRSZ : IN6ADDRSZ); > if (*pat == NULL) > { >- *pat = __alloca (sizeof (struct gaih_addrtuple)); >+ *pat = addrfree++; > (*pat)->scopeid = 0; > } > uint32_t *pataddr = (*pat)->addr; > (*pat)->next = NULL; > if (added_canon || air->canon == NULL) > (*pat)->name = NULL; >- else >- canon = (*pat)->name = strdupa (air->canon); >+ else if (canonbuf == NULL) >+ { >+ size_t canonlen = strlen (air->canon) + 1; >+ if ((req->ai_flags & AI_CANONIDN) != 0 >+ && __libc_use_alloca (alloca_used + canonlen)) >+ canonbuf = alloca_account (canonlen, alloca_used); >+ else >+ { >+ canonbuf = malloc (canonlen); >+ if (canonbuf == NULL) >+ { >+ result = -EAI_MEMORY; >+ goto free_and_return; >+ } >+ malloc_canonbuf = true; >+ } >+ canon = (*pat)->name = memcpy (canonbuf, air->canon, >+ canonlen); >+ } > > if (air->family[i] == AF_INET > && req->ai_family == AF_INET6 >@@ -759,17 +866,26 @@ gaih_inet (const char *name, const struc > free (air); > > if (at->family == AF_UNSPEC) >- return GAIH_OKIFUNSPEC | -EAI_NONAME; >+ { >+ result = GAIH_OKIFUNSPEC | -EAI_NONAME; >+ goto free_and_return; >+ } > > goto process_list; > } >- else if (err != 0 && __nss_not_use_nscd_hosts == 0) >+ else if (err == 0) >+ /* The database contains a negative entry. */ >+ goto free_and_return; >+ else if (__nss_not_use_nscd_hosts == 0) > { > if (herrno == NETDB_INTERNAL && errno == ENOMEM) >- return -EAI_MEMORY; >- if (herrno == TRY_AGAIN) >- return -EAI_AGAIN; >- return -EAI_SYSTEM; >+ result = -EAI_MEMORY; >+ else if (herrno == TRY_AGAIN) >+ result = -EAI_AGAIN; >+ else >+ result = -EAI_SYSTEM; >+ >+ goto free_and_return; > } > } > #endif >@@ -798,7 +914,19 @@ gaih_inet (const char *name, const struc > _res.options &= ~RES_USE_INET6; > > size_t tmpbuflen = 512; >- char *tmpbuf = alloca (tmpbuflen); >+ malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen); >+ assert (tmpbuf == NULL); >+ if (!malloc_tmpbuf) >+ tmpbuf = alloca_account (tmpbuflen, alloca_used); >+ else >+ { >+ tmpbuf = malloc (tmpbuflen); >+ if (tmpbuf == NULL) >+ { >+ result = -EAI_MEMORY; >+ goto free_and_return; >+ } >+ } > > while (!no_more) > { >@@ -858,18 +986,41 @@ gaih_inet (const char *name, const struc > if (cfct != NULL) > { > const size_t max_fqdn_len = 256; >- char *buf = alloca (max_fqdn_len); >+ >+ if ((req->ai_flags & AI_CANONIDN) != 0 >+ && __libc_use_alloca (alloca_used >+ + max_fqdn_len)) >+ canonbuf = alloca_account (max_fqdn_len, >+ alloca_used); >+ else >+ { >+ canonbuf = malloc (max_fqdn_len); >+ if (canonbuf == NULL) >+ { >+ result = -EAI_MEMORY; >+ goto free_and_return; >+ } >+ malloc_canonbuf = true; >+ } > char *s; > >- if (DL_CALL_FCT (cfct, (at->name ?: name, buf, >- max_fqdn_len, &s, &rc, >- &herrno)) >+ if (DL_CALL_FCT (cfct, (at->name ?: name, >+ canonbuf, >+ max_fqdn_len, >+ &s, &rc, &herrno)) > == NSS_STATUS_SUCCESS) > canon = s; > else >- /* Set to name now to avoid using >- gethostbyaddr. */ >- canon = name; >+ { >+ /* Set to name now to avoid using >+ gethostbyaddr. */ >+ if (malloc_canonbuf) >+ { >+ free (canonbuf); >+ malloc_canonbuf = false; >+ } >+ canon = name; >+ } > } > } > >@@ -900,22 +1051,27 @@ gaih_inet (const char *name, const struc > { > /* If both requests timed out report this. */ > if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) >- return -EAI_AGAIN; >+ result = -EAI_AGAIN; >+ else >+ /* We made requests but they turned out no data. The name >+ is known, though. */ >+ result = GAIH_OKIFUNSPEC | -EAI_NODATA; > >- /* We made requests but they turned out no data. The name >- is known, though. */ >- return GAIH_OKIFUNSPEC | -EAI_NODATA; >+ goto free_and_return; > } > } > > process_list: > if (at->family == AF_UNSPEC) >- return GAIH_OKIFUNSPEC | -EAI_NONAME; >+ { >+ result = GAIH_OKIFUNSPEC | -EAI_NONAME; >+ goto free_and_return; >+ } > } > else > { > struct gaih_addrtuple *atr; >- atr = at = __alloca (sizeof (struct gaih_addrtuple)); >+ atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); > memset (at, '\0', sizeof (struct gaih_addrtuple)); > > if (req->ai_family == AF_UNSPEC) >@@ -957,30 +1113,56 @@ gaih_inet (const char *name, const struc > /* Only the first entry gets the canonical name. */ > if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0) > { >+ char *tmpbuf2 = NULL; >+ bool malloc_tmpbuf2 = false; >+ > if (canon == NULL) > { > struct hostent *h = NULL; > int herrno; > struct hostent th; >- size_t tmpbuflen = 512; >- char *tmpbuf = NULL; >+ size_t tmpbuf2len = 512; > > do > { >- tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2); >+ if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len)) >+ tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len, >+ tmpbuf2len * 2, >+ alloca_used); >+ else >+ { >+ char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL, >+ 2 * tmpbuf2len); >+ if (newp == NULL) >+ { >+ if (malloc_tmpbuf2) >+ free (tmpbuf2); >+ result = -EAI_MEMORY; >+ goto free_and_return; >+ } >+ >+ tmpbuf2 = newp; >+ tmpbuf2len = 2 * tmpbuf2len; >+ malloc_tmpbuf2 = true; >+ } >+ > rc = __gethostbyaddr_r (at2->addr, > ((at2->family == AF_INET6) > ? sizeof (struct in6_addr) > : sizeof (struct in_addr)), >- at2->family, &th, tmpbuf, >- tmpbuflen, &h, &herrno); >+ at2->family, &th, tmpbuf2, >+ tmpbuf2len, &h, &herrno); > } > while (rc == ERANGE && herrno == NETDB_INTERNAL); > > if (rc != 0 && herrno == NETDB_INTERNAL) > { >+ if (malloc_tmpbuf2) >+ free (tmpbuf2); >+ > __set_h_errno (herrno); >- return -EAI_SYSTEM; >+ result = -EAI_SYSTEM; >+ goto free_and_return; > } > > if (h != NULL) >@@ -1007,11 +1189,16 @@ gaih_inet (const char *name, const struc > int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags); > if (rc != IDNA_SUCCESS) > { >+ if (malloc_tmpbuf2) >+ free (tmpbuf2); >+ > if (rc == IDNA_MALLOC_ERROR) >- return -EAI_MEMORY; >- if (rc == IDNA_DLOPEN_ERROR) >- return -EAI_SYSTEM; >- return -EAI_IDN_ENCODE; >+ result = -EAI_MEMORY; >+ else if (rc == IDNA_DLOPEN_ERROR) >+ result = -EAI_SYSTEM; >+ else >+ result = -EAI_IDN_ENCODE; >+ goto free_and_return; > } > /* In case the output string is the same as the input > string no new string has been allocated. Otherwise >@@ -1025,10 +1212,25 @@ gaih_inet (const char *name, const struc > #ifdef HAVE_LIBIDN > make_copy: > #endif >- canon = strdup (canon); >- if (canon == NULL) >- return -EAI_MEMORY; >+ if (malloc_canonbuf) >+ /* We already allocated the string using malloc. */ >+ malloc_canonbuf = false; >+ else >+ { >+ canon = strdup (canon); >+ if (canon == NULL) >+ { >+ if (malloc_tmpbuf2) >+ free (tmpbuf2); >+ >+ result = -EAI_MEMORY; >+ goto free_and_return; >+ } >+ } > } >+ >+ if (malloc_tmpbuf2) >+ free (tmpbuf2); > } > > family = at2->family; >@@ -1054,7 +1256,8 @@ gaih_inet (const char *name, const struc > if (ai == NULL) > { > free ((char *) canon); >- return -EAI_MEMORY; >+ result = -EAI_MEMORY; >+ goto free_and_return; > } > > ai->ai_flags = req->ai_flags; >@@ -1107,7 +1310,18 @@ gaih_inet (const char *name, const struc > at2 = at2->next; > } > } >- return 0; >+ >+ free_and_return: >+ if (malloc_name) >+ free ((char *) name); >+ if (malloc_addrmem) >+ free (addrmem); >+ if (malloc_canonbuf) >+ free (canonbuf); >+ if (malloc_tmpbuf) >+ free (tmpbuf); >+ >+ return result; > } > > #if 0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 797096
: 583711 |
583712