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 583712 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 #2
glibc-rh797096-2.patch (text/plain), 19.20 KB, created by
Jeff Law
on 2012-05-11 03:47:07 UTC
(
hide
)
Description:
Patch part #2
Filename:
MIME Type:
Creator:
Jeff Law
Created:
2012-05-11 03:47:07 UTC
Size:
19.20 KB
patch
obsolete
>diff -rup a/nis/nss_nis/nis-alias.c b/nis/nss_nis/nis-alias.c >--- a/nis/nss_nis/nis-alias.c 2006-04-08 20:08:28.000000000 -0600 >+++ b/nis/nss_nis/nis-alias.c 2012-02-28 13:10:41.077971912 -0700 >@@ -142,10 +142,10 @@ internal_nis_getaliasent_r (struct alias > int yperr; > > if (new_start) >- yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result, >+ yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result, > &len); > else >- yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey, >+ yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey, > &keylen, &result, &len); > > if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) >@@ -153,20 +153,20 @@ internal_nis_getaliasent_r (struct alias > enum nss_status retval = yperr2nss (yperr); > > if (retval == NSS_STATUS_TRYAGAIN) >- *errnop = errno; >- return retval; >- } >+ *errnop = errno; >+ return retval; >+ } > > if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) >- { >+ { > free (result); >- *errnop = ERANGE; >- return NSS_STATUS_TRYAGAIN; >- } >+ *errnop = ERANGE; >+ return NSS_STATUS_TRYAGAIN; >+ } > char *p = strncpy (buffer, result, len); > buffer[len] = '\0'; > while (isspace (*p)) >- ++p; >+ ++p; > free (result); > > parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer, >@@ -213,13 +213,25 @@ _nss_nis_getaliasbyname_r (const char *n > return NSS_STATUS_UNAVAIL; > } > >- size_t namlen = strlen (name); >- char name2[namlen + 1]; >- > char *domain; > if (__builtin_expect (yp_get_default_domain (&domain), 0)) > return NSS_STATUS_UNAVAIL; > >+ size_t namlen = strlen (name); >+ char *name2; >+ int use_alloca = __libc_use_alloca (namlen + 1); >+ if (use_alloca) >+ name2 = __alloca (namlen + 1); >+ else >+ { >+ name2 = malloc (namlen + 1); >+ if (name2 == NULL) >+ { >+ *errnop = ENOMEM; >+ return NSS_STATUS_TRYAGAIN; >+ } >+ } >+ > /* Convert name to lowercase. */ > size_t i; > for (i = 0; i < namlen; ++i) >@@ -230,6 +242,9 @@ _nss_nis_getaliasbyname_r (const char *n > int len; > int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len); > >+ if (!use_alloca) >+ free (name2); >+ > if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) > { > enum nss_status retval = yperr2nss (yperr); >Only in b/nis/nss_nis: nis-alias.c.rej >diff -rup a/posix/glob.c b/posix/glob.c >--- a/posix/glob.c 2006-09-30 09:08:44.000000000 -0600 >+++ b/posix/glob.c 2012-02-28 14:15:46.970249576 -0700 >@@ -194,7 +194,7 @@ static const char *next_brace_sub (const > > static int glob_in_dir (const char *pattern, const char *directory, > int flags, int (*errfunc) (const char *, int), >- glob_t *pglob); >+ glob_t *pglob, size_t alloca_used); > > #if !defined _LIBC || !defined GLOB_ONLY_P > static int prefix_array (const char *prefix, char **array, size_t n) __THROW; >@@ -246,10 +246,15 @@ glob (pattern, flags, errfunc, pglob) > glob_t *pglob; > { > const char *filename; >- const char *dirname; >+ char *dirname = NULL; > size_t dirlen; > int status; > size_t oldcount; >+ int malloc_dirname = 0 >+ int retval = 0; >+#ifdef _LIBC >+ size_t alloca_used = 0; >+#endif > > if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) > { >@@ -298,20 +303,26 @@ glob (pattern, flags, errfunc, pglob) > const char *next; > const char *rest; > size_t rest_len; >-#ifdef __GNUC__ >- char onealt[strlen (pattern) - 1]; >-#else >- char *onealt = (char *) malloc (strlen (pattern) - 1); >- if (onealt == NULL) >+ char *onealt; >+ size_t pattern_len = strlen (pattern) - 1; >+#ifdef _LIBC >+ int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len); >+ if (alloca_onealt) >+ onealt = alloca_account (pattern_len, alloca_used); >+ else >+#endif > { >- if (!(flags & GLOB_APPEND)) >+ onealt = (char *) malloc (pattern_len); >+ if (onealt == NULL) > { >- pglob->gl_pathc = 0; >- pglob->gl_pathv = NULL; >+ if (!(flags & GLOB_APPEND)) >+ { >+ pglob->gl_pathc = 0; >+ pglob->gl_pathv = NULL; >+ } >+ return GLOB_NOSPACE; > } >- return GLOB_NOSPACE; > } >-#endif > > /* We know the prefix for all sub-patterns. */ > alt_start = mempcpy (onealt, pattern, begin - pattern); >@@ -322,9 +333,11 @@ glob (pattern, flags, errfunc, pglob) > if (next == NULL) > { > /* It is an illegal expression. */ >-#ifndef __GNUC__ >- free (onealt); >+ illegal_brace: >+#ifdef _LIBC >+ if (__builtin_expect (!alloca_onealt, 0)) > #endif >+ free (onealt); > return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); > } > >@@ -334,13 +347,8 @@ glob (pattern, flags, errfunc, pglob) > { > rest = next_brace_sub (rest + 1, flags); > if (rest == NULL) >- { >- /* It is an illegal expression. */ >-#ifndef __GNUC__ >- free (onealt); >-#endif >- return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); >- } >+ /* It is an illegal expression. */ >+ goto illegal_brace; > } > /* Please note that we now can be sure the brace expression > is well-formed. */ >@@ -376,9 +384,10 @@ glob (pattern, flags, errfunc, pglob) > /* If we got an error, return it. */ > if (result && result != GLOB_NOMATCH) > { >-#ifndef __GNUC__ >- free (onealt); >+#ifdef _LIBC >+ if (__builtin_expect (!alloca_onealt, 0)) > #endif >+ free (onealt); > if (!(flags & GLOB_APPEND)) > { > globfree (pglob); >@@ -396,9 +405,10 @@ glob (pattern, flags, errfunc, pglob) > assert (next != NULL); > } > >-#ifndef __GNUC__ >- free (onealt); >+#ifdef _LIBC >+ if (__builtin_expect (!alloca_onealt, 0)) > #endif >+ free (onealt); > > if (pglob->gl_pathc != firstc) > /* We found some entries. */ >@@ -424,7 +434,7 @@ glob (pattern, flags, errfunc, pglob) > case is nothing but a notation for a directory. */ > if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') > { >- dirname = pattern; >+ dirname = (char *) pattern; > dirlen = strlen (pattern); > > /* Set FILENAME to NULL as a special flag. This is ugly but >@@ -436,9 +446,9 @@ glob (pattern, flags, errfunc, pglob) > { > filename = pattern; > #ifdef _AMIGA >- dirname = ""; >+ dirname = (char *) ""; > #else >- dirname = "."; >+ dirname = (char *) "."; > #endif > dirlen = 0; > } >@@ -472,7 +482,17 @@ glob (pattern, flags, errfunc, pglob) > from "d:/", since "d:" and "d:/" are not the same.*/ > } > #endif >- newp = (char *) __alloca (dirlen + 1); >+#ifdef _LIBC >+ if (__libc_use_alloca (alloca_used + dirlen + 1)) >+ newp = alloca_account (dirlen + 1, alloca_used); >+ else >+#endif >+ { >+ newp = malloc (dirlen + 1); >+ if (newp == NULL) >+ return GLOB_NOSPACE; >+ malloc_dirname = 1; >+ } > *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; > dirname = newp; > ++filename; >@@ -490,7 +510,8 @@ glob (pattern, flags, errfunc, pglob) > if (val == 0) > pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) > | (flags & GLOB_MARK)); >- return val; >+ retval = val; >+ goto out; > } > } > >@@ -520,7 +541,8 @@ glob (pattern, flags, errfunc, pglob) > if (dirname[1] == '\0' || dirname[1] == '/') > { > /* Look up home directory. */ >- const char *home_dir = getenv ("HOME"); >+ char *home_dir = getenv ("HOME"); >+ int malloc_home_dir = 0; > # ifdef _AMIGA > if (home_dir == NULL || home_dir[0] == '\0') > home_dir = "SYS:"; >@@ -539,7 +561,7 @@ glob (pattern, flags, errfunc, pglob) > /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try > a moderate value. */ > buflen = 20; >- name = (char *) __alloca (buflen); >+ name = alloca_account (buflen, alloca_used); > > success = getlogin_r (name, buflen) == 0; > if (success) >@@ -549,6 +571,7 @@ glob (pattern, flags, errfunc, pglob) > long int pwbuflen = GETPW_R_SIZE_MAX (); > char *pwtmpbuf; > struct passwd pwbuf; >+ int malloc_pwtmpbuf = 0; > int save = errno; > > # ifndef _LIBC >@@ -557,7 +580,18 @@ glob (pattern, flags, errfunc, pglob) > Try a moderate value. */ > pwbuflen = 1024; > # endif >- pwtmpbuf = (char *) __alloca (pwbuflen); >+ if (__libc_use_alloca (alloca_used + pwbuflen)) >+ pwtmpbuf = alloca_account (pwbuflen, alloca_used); >+ else >+ { >+ pwtmpbuf = malloc (pwbuflen); >+ if (pwtmpbuf == NULL) >+ { >+ retval = GLOB_NOSPACE; >+ goto out; >+ } >+ malloc_pwtmpbuf = 1; >+ } > > while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) > != 0) >@@ -567,26 +601,71 @@ glob (pattern, flags, errfunc, pglob) > p = NULL; > break; > } >-# ifdef _LIBC >- pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen, >+ >+ if (!malloc_pwtmpbuf >+ && __libc_use_alloca (alloca_used >+ + 2 * pwbuflen)) >+ pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen, >+ 2 * pwbuflen, >+ alloca_used); >+ else >+ { >+ char *newp = realloc (malloc_pwtmpbuf >+ ? pwtmpbuf : NULL, > 2 * pwbuflen); >-# else >- pwbuflen *= 2; >- pwtmpbuf = (char *) __alloca (pwbuflen); >-# endif >+ if (newp == NULL) >+ { >+ if (__builtin_expect (malloc_pwtmpbuf, 0)) >+ free (pwtmpbuf); >+ retval = GLOB_NOSPACE; >+ goto out; >+ } >+ pwtmpbuf = newp; >+ pwbuflen = 2 * pwbuflen; >+ malloc_pwtmpbuf = 1; >+ } > __set_errno (save); > } > # else > p = getpwnam (name); > # endif > if (p != NULL) >- home_dir = p->pw_dir; >+ { >+ if (!malloc_pwtmpbuf) >+ home_dir = p->pw_dir; >+ else >+ { >+ size_t home_dir_len = strlen (p->pw_dir) + 1; >+ if (__libc_use_alloca (alloca_used + home_dir_len)) >+ home_dir = alloca_account (home_dir_len, >+ alloca_used); >+ else >+ { >+ home_dir = malloc (home_dir_len); >+ if (home_dir == NULL) >+ { >+ free (pwtmpbuf); >+ retval = GLOB_NOSPACE; >+ goto out; >+ } >+ malloc_home_dir = 1; >+ } >+ memcpy (home_dir, p->pw_dir, home_dir_len); >+ >+ free (pwtmpbuf); >+ } >+ } > } > } > if (home_dir == NULL || home_dir[0] == '\0') > { > if (flags & GLOB_TILDE_CHECK) >- return GLOB_NOMATCH; >+ { >+ if (__builtin_expect (malloc_home_dir, 0)) >+ free (home_dir); >+ retval = GLOB_NOMATCH; >+ goto out; >+ } > else > home_dir = "~"; /* No luck. */ > } >@@ -594,22 +673,51 @@ glob (pattern, flags, errfunc, pglob) > # endif > /* Now construct the full directory. */ > if (dirname[1] == '\0') >- dirname = home_dir; >+ { >+ if (__builtin_expect (malloc_dirname, 0)) >+ free (dirname); >+ >+ dirname = home_dir; >+ dirlen = strlen (dirname); >+ malloc_dirname = malloc_home_dir; >+ } > else > { > char *newp; > size_t home_len = strlen (home_dir); >- newp = (char *) __alloca (home_len + dirlen); >+ int use_alloca = __libc_use_alloca (alloca_used >+ + home_len + dirlen); >+ if (use_alloca) >+ newp = alloca_account (home_len + dirlen, alloca_used); >+ else >+ { >+ newp = malloc (home_len + dirlen); >+ if (newp == NULL) >+ { >+ if (__builtin_expect (malloc_home_dir, 0)) >+ free (home_dir); >+ retval = GLOB_NOSPACE; >+ goto out; >+ } >+ } >+ > mempcpy (mempcpy (newp, home_dir, home_len), > &dirname[1], dirlen); >+ >+ if (__builtin_expect (malloc_dirname, 0)) >+ free (dirname); >+ > dirname = newp; >+ dirlen += home_len - 1; >+ malloc_dirname = !use_alloca; > } > } > # if !defined _AMIGA && !defined WINDOWS32 > else > { > char *end_name = strchr (dirname, '/'); >- const char *user_name; >+ char *user_name; >+ int malloc_user_name = 0; > const char *home_dir; > > if (end_name == NULL) >@@ -617,7 +725,19 @@ glob (pattern, flags, errfunc, pglob) > else > { > char *newp; >- newp = (char *) __alloca (end_name - dirname); >+ if (__libc_use_alloca (alloca_used + (end_name - dirname))) >+ newp = alloca_account (end_name - dirname, alloca_used); >+ else >+ { >+ newp = malloc (end_name - dirname); >+ if (newp == NULL) >+ { >+ retval = GLOB_NOSPACE; >+ goto out; >+ } >+ malloc_user_name = 1; >+ } >+ > *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) > = '\0'; > user_name = newp; >@@ -629,6 +749,7 @@ glob (pattern, flags, errfunc, pglob) > # if defined HAVE_GETPWNAM_R || defined _LIBC > long int buflen = GETPW_R_SIZE_MAX (); > char *pwtmpbuf; >+ int malloc_pwtmpbuf = 0; > struct passwd pwbuf; > int save = errno; > >@@ -638,7 +759,21 @@ glob (pattern, flags, errfunc, pglob) > moderate value. */ > buflen = 1024; > # endif >- pwtmpbuf = (char *) __alloca (buflen); >+ if (__libc_use_alloca (alloca_used + buflen)) >+ pwtmpbuf = alloca_account (buflen, alloca_used); >+ else >+ { >+ pwtmpbuf = malloc (buflen); >+ if (pwtmpbuf == NULL) >+ { >+ nomem_getpw: >+ if (__builtin_expect (malloc_user_name, 0)) >+ free (user_name); >+ retval = GLOB_NOSPACE; >+ goto out; >+ } >+ malloc_pwtmpbuf = 1; >+ } > > while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) > { >@@ -647,38 +782,75 @@ glob (pattern, flags, errfunc, pglob) > p = NULL; > break; > } >-# ifdef _LIBC >- pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen); >-# else >- buflen *= 2; >- pwtmpbuf = __alloca (buflen); >-# endif >+ if (!malloc_pwtmpbuf >+ && __libc_use_alloca (alloca_used + 2 * buflen)) >+ pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen, >+ 2 * buflen, alloca_used); >+ else >+ { >+ char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL, >+ 2 * buflen); >+ if (newp == NULL) >+ { >+ if (__builtin_expect (malloc_pwtmpbuf, 0)) >+ free (pwtmpbuf); >+ goto nomem_getpw; >+ } >+ pwtmpbuf = newp; >+ malloc_pwtmpbuf = 1; >+ } > __set_errno (save); > } > # else > p = getpwnam (user_name); > # endif >+ >+ if (__builtin_expect (malloc_user_name, 0)) >+ free (user_name); >+ >+ /* If we found a home directory use this. */ > if (p != NULL) >- home_dir = p->pw_dir; >+ { >+ size_t home_len = strlen (p->pw_dir); >+ size_t rest_len = end_name == NULL ? 0 : strlen (end_name); >+ >+ if (__builtin_expect (malloc_dirname, 0)) >+ free (dirname); >+ malloc_dirname = 0; >+ >+ if (__libc_use_alloca (alloca_used + home_len + rest_len + 1)) >+ dirname = alloca_account (home_len + rest_len + 1, >+ alloca_used); >+ else >+ { >+ dirname = malloc (home_len + rest_len + 1); >+ if (dirname == NULL) >+ { >+ if (__builtin_expect (malloc_pwtmpbuf, 0)) >+ free (pwtmpbuf); >+ retval = GLOB_NOSPACE; >+ goto out; >+ } >+ malloc_dirname = 1; >+ } >+ *((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len), >+ end_name, rest_len)) = '\0'; >+ >+ dirlen = home_len + rest_len; >+ >+ if (__builtin_expect (malloc_pwtmpbuf, 0)) >+ free (pwtmpbuf); >+ } > else >- home_dir = NULL; >- } >- /* If we found a home directory use this. */ >- if (home_dir != NULL) >- { >- char *newp; >- size_t home_len = strlen (home_dir); >- size_t rest_len = end_name == NULL ? 0 : strlen (end_name); >- newp = (char *) __alloca (home_len + rest_len + 1); >- *((char *) mempcpy (mempcpy (newp, home_dir, home_len), >- end_name, rest_len)) = '\0'; >- dirname = newp; >- } >- else >- if (flags & GLOB_TILDE_CHECK) >- /* We have to regard it as an error if we cannot find the >- home directory. */ >- return GLOB_NOMATCH; >+ { >+ if (__builtin_expect (malloc_pwtmpbuf, 0)) >+ free (pwtmpbuf); >+ >+ if (flags & GLOB_TILDE_CHECK) >+ /* We have to regard it as an error if we cannot find the >+ home directory. */ >+ return GLOB_NOMATCH; >+ } > } > # endif /* Not Amiga && not WINDOWS32. */ > } >@@ -779,7 +951,7 @@ glob (pattern, flags, errfunc, pglob) > status = glob_in_dir (filename, dirs.gl_pathv[i], > ((flags | GLOB_APPEND) > & ~(GLOB_NOCHECK | GLOB_NOMAGIC)), >- errfunc, pglob); >+ errfunc, pglob, alloca_used); > if (status == GLOB_NOMATCH) > /* No matches in this directory. Try the next. */ > continue; >@@ -855,7 +1027,7 @@ glob (pattern, flags, errfunc, pglob) > { > int old_pathc = pglob->gl_pathc; > >- status = glob_in_dir (filename, dirname, flags, errfunc, pglob); >+ status = glob_in_dir (filename, dirname, flags, errfunc, pglob, alloca_used); > if (status != 0) > return status; > >@@ -908,7 +1080,11 @@ glob (pattern, flags, errfunc, pglob) > sizeof (char *), collated_compare); > } > >- return 0; >+ out: >+ if (__builtin_expect (malloc_dirname, 0)) >+ free (dirname); >+ >+ return retval; > } > #if defined _LIBC && !defined glob > libc_hidden_def (glob) >@@ -1086,7 +1262,7 @@ link_exists_p (const char *dir, size_t d > static int > glob_in_dir (const char *pattern, const char *directory, int flags, > int (*errfunc) (const char *, int), >- glob_t *pglob) >+ glob_t *pglob, size_t alloca_used) > { > size_t dirlen = strlen (directory); > void *stream = NULL; >@@ -1101,11 +1277,12 @@ glob_in_dir (const char *pattern, const > struct globnames *names = &init_names; > struct globnames *names_alloca = &init_names; > size_t nfound = 0; >- size_t allocasize = sizeof (init_names); > size_t cur = 0; > int meta; > int save; > >+ alloca_used += sizeof (init_names); >+ > init_names.next = NULL; > init_names.count = INITIAL_COUNT; > >@@ -1122,20 +1299,37 @@ glob_in_dir (const char *pattern, const > { > /* Since we use the normal file functions we can also use stat() > to verify the file is there. */ >- struct stat st; >- struct_stat64 st64; >+ union >+ { >+ struct stat st; >+ struct_stat64 st64; >+ } ust; > size_t patlen = strlen (pattern); >- char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1); >+ int alloca_fullname = __libc_use_alloca (alloca_used >+ + dirlen + 1 + patlen + 1); >+ char *fullname; >+ if (alloca_fullname) >+ fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used); >+ else >+ { >+ fullname = malloc (dirlen + 1 + patlen + 1); >+ if (fullname == NULL) >+ return GLOB_NOSPACE; >+ } > > mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), > "/", 1), > pattern, patlen + 1); > if (((flags & GLOB_ALTDIRFUNC) >- ? (*pglob->gl_stat) (fullname, &st) >- : __stat64 (fullname, &st64)) == 0) >+ ? (*pglob->gl_stat) (fullname, &ust.st) >+ : __stat64 (fullname, &ust.st64)) == 0) > /* We found this file to be existing. Now tell the rest > of the function to copy this name into the result. */ > flags |= GLOB_NOCHECK; >+ >+ if (__builtin_expect (!alloca_fullname, 0)) >+ free (fullname); >+ > } > else > { >@@ -1233,9 +1427,9 @@ glob_in_dir (const char *pattern, const > size_t size = (sizeof (struct globnames) > + ((count - INITIAL_COUNT) > * sizeof (char *))); >- allocasize += size; >- if (__libc_use_alloca (allocasize)) >- newnames = names_alloca = __alloca (size); >+ if (__libc_use_alloca (alloca_used + size)) >+ newnames = names_alloca >+ = alloca_account (size, alloca_used); > else if ((newnames = malloc (size)) > == NULL) > goto memory_error; >Only in b/posix: glob.c.orig >Only in b/posix: glob.c.rej
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