FreeBSD Bugzilla – Attachment 177035 Details for
Bug 214546
www/libwww: Security vulnerabilities
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
libwww-5.4.0_6.patch
libwww-5.4.0_6.patch (text/plain), 18.60 KB, created by
Danilo G. Baio
on 2016-11-15 20:54:42 UTC
(
hide
)
Description:
libwww-5.4.0_6.patch
Filename:
MIME Type:
Creator:
Danilo G. Baio
Created:
2016-11-15 20:54:42 UTC
Size:
18.60 KB
patch
obsolete
>Index: Makefile >=================================================================== >--- Makefile (revision 426176) >+++ Makefile (working copy) >@@ -3,23 +3,28 @@ > > PORTNAME= libwww > PORTVERSION= 5.4.0 >-PORTREVISION= 5 >+PORTREVISION= 6 > CATEGORIES= www devel > MASTER_SITES= http://www.w3.org/Library/Distribution/ > DISTNAME= w3c-${PORTNAME}-${PORTVERSION} > > MAINTAINER= marius@nuenneri.ch >-COMMENT= The W3C Reference Library >+COMMENT= W3C Reference Library >+ >+LICENSE= W3C >+LICENSE_NAME= W3C IPR SOFTWARE NOTICE >+LICENSE_FILE= ${WRKSRC}/LICENSE.html >+LICENSE_PERMS= dist-mirror dist-sell pkg-mirror pkg-sell auto-accept > > GNU_CONFIGURE= yes > CONFIGURE_ARGS= --with-zlib --with-ssl=${OPENSSLBASE} >-USES= perl5 gmake libtool tar:tgz >+USES= gmake libtool perl5 ssl tar:tgz > USE_PERL5= build > USE_LDCONFIG= yes >-USE_OPENSSL= yes > > post-install: > ${INSTALL_DATA} ${WRKSRC}/modules/expat/xmlparse/xmlparse.h \ > ${STAGEDIR}${PREFIX}/include/w3c-libwww/ >+ ${STRIP_CMD} ${STAGEDIR}${PREFIX}/lib/*.so > > .include <bsd.port.mk> >Index: files/patch-Library__src__HTMIMImp.c >=================================================================== >--- files/patch-Library__src__HTMIMImp.c (revision 426176) >+++ files/patch-Library__src__HTMIMImp.c (working copy) >@@ -1,6 +1,6 @@ >---- Library/src/HTMIMImp.c.orig Sun Jun 30 22:51:48 2002 >-+++ Library/src/HTMIMImp.c Sun Jun 30 22:52:01 2002 >-@@ -226,7 +226,7 @@ >+--- Library/src/HTMIMImp.c.orig 1999-02-22 22:10:11 UTC >++++ Library/src/HTMIMImp.c >+@@ -226,7 +226,7 @@ PRIVATE int HTFindInt(char * haystack, c > int value = deflt; > if (start != NULL) { > start += strlen(needle); >Index: files/patch-Library_src_HTBound.c >=================================================================== >--- files/patch-Library_src_HTBound.c (nonexistent) >+++ files/patch-Library_src_HTBound.c (working copy) >@@ -0,0 +1,525 @@ >+# $FreeBSD$ >+ >+# CVE-2005-3183 >+ >+--- Library/src/HTBound.c.orig 1999-02-22 22:10:10 UTC >++++ Library/src/HTBound.c >+@@ -11,9 +11,12 @@ >+ ** >+ ** Authors >+ ** HF Henrik Frystyk <frystyk@w3.org> >++** SV Sam Varshavchik <mrsam@courier-mta.com> >+ ** >+ ** History: >+ ** Nov 95 Written from scratch >++** SV Jun 05 Rewrote HTBoundary_put_block. Fixed many bugs+segfaults. >++** SV Jul 05 Fix double-counting of processed bytes. >+ ** >+ */ >+ >+@@ -23,104 +26,395 @@ >+ #include "WWWCore.h" >+ #include "HTMerge.h" >+ #include "HTReqMan.h" >++#include "HTNetMan.h" >++#include "HTChannl.h" >+ #include "HTBound.h" /* Implemented here */ >+ >+-#define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l) >++#define PUTBLOCK(b, l) (me->target ? (*me->target->isa->put_block)(me->target, b, l):HT_OK) >++ >+ #define PUTDEBUG(b, l) (*me->debug->isa->put_block)(me->debug, b, l) >+ #define FREE_TARGET (*me->target->isa->_free)(me->target) >+ >+ struct _HTStream { >+ const HTStreamClass * isa; >++ HTNet * net; >+ HTStream * target; >+ HTStream * orig_target; >+ HTFormat format; >+ HTStream * debug; /* For preamble and epilog */ >+ HTRequest * request; >+- BOOL body; /* Body or preamble|epilog */ >+- HTEOLState state; >+- int dash; /* Number of dashes */ >+ char * boundary; >+- char * bpos; >++ >++ BOOL keptcrlf; >++ int (*state)(HTStream *, const char *, int); >++ >++ char *boundary_ptr; >++ >+ }; >+ >++PRIVATE int HTBoundary_flush (HTStream * me); >++ >+ /* ------------------------------------------------------------------------- */ >+ >++PRIVATE int start_of_line (HTStream * me, const char * b, int l); >++PRIVATE int seen_dash (HTStream * me, const char * b, int l); >++PRIVATE int seen_doubledash (HTStream * me, const char * b, int l); >++PRIVATE int seen_delimiter_nonterminal(HTStream * me, const char * b, int l); >++PRIVATE int seen_delimiter_nonterminal_CR(HTStream * me, const char * b, int l); >++PRIVATE int seen_delimiter_dash(HTStream * me, const char * b, int l); >++PRIVATE int seen_delimiter_terminal(HTStream * me, const char * b, int l); >++PRIVATE int seen_delimiter_terminal_CR(HTStream * me, const char * b, int l); >++PRIVATE int not_delimiter(HTStream * me, const char * b, int l, int extra); >++PRIVATE int seen_nothing(HTStream * me, const char * b, int l); >++PRIVATE int seen_cr(HTStream * me, const char * b, int l); >++PRIVATE void process_boundary(HTStream *me, int isterminal); >++ >++#define UNUSED(l) (l=l) /* Shut up about unused variables */ >++ >+ PRIVATE int HTBoundary_put_block (HTStream * me, const char * b, int l) >+ { >+- const char *start = b; >+- const char *end = b; >+- while (l-- > 0) { >+- if (me->state == EOL_FCR) { >+- me->state = (*b == LF) ? EOL_FLF : EOL_BEGIN; >+- } else if (me->state == EOL_FLF) { >+- if (me->dash == 2) { >+- while (l>0 && *me->bpos && *me->bpos==*b) l--, me->bpos++, b++; >+- if (!*me->bpos) { >+- HTTRACE(STREAM_TRACE, "Boundary.... `%s\' found\n" _ me->boundary); >+- me->bpos = me->boundary; >+- me->body = YES; >+- me->state = EOL_DOT; >+- } else if (l>0) { >+- me->dash = 0; >+- me->bpos = me->boundary; >+- me->state = EOL_BEGIN; >+- } >+- } >+- if (*b == '-') { >+- me->dash++; >+- } else if (*b != CR && *b != LF) { >+- me->dash = 0; >+- me->state = EOL_BEGIN; >+- } >+- } else if (me->state == EOL_SLF) { /* Look for closing '--' */ >+- if (me->dash == 4) { >+- if (end > start) { >+- int status = PUTBLOCK(start, end-start); >+- if (status != HT_OK) return status; >++ /* >++ ** The HTBoundary object gets attached downstream of HTMime. >++ ** The HTBoundary object creates another HTMime object downstream of >++ ** the HTBoundary object. >++ ** >++ ** When we push data downstream to the second HTBoundary object, it >++ ** updates the bytes read count in the HTNet object. >++ ** >++ ** When we return to the parent HTMime object, itupdates the >++ ** bytes read count in the HTNet object again. Oops. >++ ** >++ ** Same thing happens with the consumed byte count. We can prevent >++ ** the consumed byte counts from being updated by temporary setting >++ ** the input channel stream pointer to NULL, but for the byte counts >++ ** we have to save them and restore them before existing. >++ ** >++ ** This bug was discovered by chance when a multipart/partial response >++ ** was partially received, and as a result of double-counting the >++ ** real response got cut off (because HTMime thought that more bytes >++ ** were processed than actually were, thus it processed only the >++ ** partial count of the remaining bytes in the response). When the >++ ** multipart/partial response was received all at once this bug did >++ ** not get triggered. >++ */ >++ >++ HTHost *host=HTNet_host(me->net); >++ HTChannel *c=HTHost_channel(host); >++ HTInputStream *i=HTChannel_input(c); >++ >++ long saveBytesRead=HTNet_bytesRead(me->net); >++ long saveHeaderBytesRead=HTNet_headerBytesRead(me->net); >++ >++ if (i) >++ HTChannel_setInput(c, NULL); >++ >++ HTTRACE(STREAM_TRACE, "Boundary: processing %d bytes\n" _ l); >++ /* Main loop consumes all input */ >++ >++ while (l) >++ { >++ int n= (*me->state)(me, b, l); >++ >++ if (n == 0) >++ return HT_ERROR; >++ b += n; >++ l -= n; >++ } >++ >++ if (i) >++ HTChannel_setInput(c, i); >++ HTNet_setBytesRead(me->net, saveBytesRead); >++ HTNet_setHeaderBytesRead(me->net, saveHeaderBytesRead); >++ >++ return HT_OK; >++} >++ >++/* >++** Start of line, keptcrlf=YES if we've kept the preceding CRLF from downstream >++** and we'll pass it along if we decide that this is not a boundary delimiter. >++*/ >++ >++PRIVATE int start_of_line (HTStream * me, const char * b, int l) >++{ >++ if (*b != '-') >++ return not_delimiter(me, b, l, 0); >++ >++ HTTRACE(STREAM_TRACE, "Boundary: start of line: input '-'\n"); >++ >++ me->state= seen_dash; >++ >++ return 1; >++} >++ >++/* >++** Line: - >++*/ >++ >++PRIVATE int seen_dash (HTStream * me, const char * b, int l) >++{ >++ if (*b != '-') >++ return not_delimiter(me, b, l, 1); >++ >++ HTTRACE(STREAM_TRACE, "Boundary: start of line: input '--'\n"); >++ >++ me->state= seen_doubledash; >++ me->boundary_ptr=me->boundary; >++ return 1; >++} >++ >++/* >++** Line: -- >++*/ >++ >++PRIVATE int seen_doubledash (HTStream * me, const char * b, int l) >++{ >++ me->state=seen_doubledash; >++ >++ if (*me->boundary_ptr) >++ { >++ if (*b != *me->boundary_ptr) >++ { >++ return not_delimiter(me, b, l, >++ me->boundary_ptr - me->boundary >++ + 2); >+ } >+- HTTRACE(STREAM_TRACE, "Boundary.... Ending\n"); >+- start = b; >+- me->dash = 0; >+- me->state = EOL_BEGIN; >+- } >+- if (*b == '-') { >+- me->dash++; >+- } else if (*b != CR && *b != LF) { >+- me->dash = 0; >+- me->state = EOL_BEGIN; >++ ++me->boundary_ptr; >++ return 1; >+ } >+- me->body = NO; >+- } else if (me->state == EOL_DOT) { >+- int status; >+- if (me->body) { >+- if (me->target) FREE_TARGET; >++ >++ /* >++ ** Line: --delimiter >++ */ >++ >++ if (*b == '-') >++ { >++ HTTRACE(STREAM_TRACE, >++ "Boundary: start of line: input '--%s-'\n" >++ _ me->boundary); >++ >++ me->state=seen_delimiter_dash; >++ return 1; >++ } >++ >++ HTTRACE(STREAM_TRACE, >++ "Boundary: Found: '--%s'\n" _ me->boundary); >++ >++ return seen_delimiter_nonterminal(me, b, l); >++} >++ >++/* >++** Line: --delimiter >++** >++** Waiting for CRLF. >++*/ >++ >++ >++PRIVATE int seen_delimiter_nonterminal(HTStream * me, const char * b, int l) >++{ >++ UNUSED(l); >++ >++ me->state=seen_delimiter_nonterminal; >++ if (*b == CR) >++ me->state=seen_delimiter_nonterminal_CR; >++ >++ return 1; >++} >++ >++/* >++** Line: --delimiter<CR> >++*/ >++ >++PRIVATE int seen_delimiter_nonterminal_CR(HTStream * me, const char * b, int l) >++{ >++ HTTRACE(STREAM_TRACE, >++ "Boundary: Found: '--%s<CR>'\n" _ me->boundary); >++ >++ if (*b != LF) >++ return seen_delimiter_nonterminal(me, b, l); >++ >++ HTTRACE(STREAM_TRACE, >++ "Boundary: Found: '--%s<CR><LF>'\n" _ me->boundary); >++ >++ process_boundary(me, NO); >++ return 1; >++} >++ >++/* >++** Line: --delimiter- >++*/ >++ >++PRIVATE int seen_delimiter_dash(HTStream * me, const char * b, int l) >++{ >++ if (*b != '-') >++ return seen_delimiter_nonterminal(me, b, l); >++ >++ HTTRACE(STREAM_TRACE, >++ "Boundary: start of line: input '--%s--'\n" >++ _ me->boundary); >++ >++ me->state=seen_delimiter_terminal; >++ return 1; >++} >++ >++/* >++** Line: --delimiter-- >++*/ >++ >++PRIVATE int seen_delimiter_terminal(HTStream * me, const char * b, int l) >++{ >++ UNUSED(l); >++ >++ me->state=seen_delimiter_terminal; >++ >++ if (*b == CR) >++ me->state=seen_delimiter_terminal_CR; >++ return 1; >++} >++/* >++** Line: --delimiter--<CR> >++*/ >++ >++PRIVATE int seen_delimiter_terminal_CR(HTStream * me, const char * b, int l) >++{ >++ HTTRACE(STREAM_TRACE, >++ "Boundary: Found '--%s--<CR>'\n" >++ _ me->boundary); >++ >++ if (*b != LF) >++ return seen_delimiter_terminal(me, b, l); >++ HTTRACE(STREAM_TRACE, >++ "Boundary: Found '--%s--<CR><LF>'\n" >++ _ me->boundary); >++ >++ process_boundary(me, YES); >++ return 1; >++} >++ >++/* >++** Beginning of the line does not contain a delimiter. >++** >++** >++** extra: Count of characters in a partially matched delimiter. Since it's >++** not a delimiter this is content that needs to go downstream. >++*/ >++ >++PRIVATE int not_delimiter(HTStream * me, const char * b, int l, int extra) >++{ >++ HTTRACE(STREAM_TRACE, "Boundary: not a delimiter line\n"); >++ >++ if (me->keptcrlf) >++ { >++ HTTRACE(STREAM_TRACE, "Boundary: Sending previous line's <CR><LF>\n"); >++ /* >++ ** Did not process CRLF from previous line, because prev CRLF >++ ** is considered a part of the delimiter. See MIME RFC. >++ */ >++ >++ me->keptcrlf=NO; >++ if (PUTBLOCK("\r\n", 2) != HT_OK) >++ return 0; >++ } >++ >++ /* >++ ** Potentially matched some of: --DELIMITER >++ */ >++ >++ if (extra) >++ { >++ HTTRACE(STREAM_TRACE, "Boundary: Sending partially-matched %d characters\n" _ extra); >++ >++ if (PUTBLOCK("--", extra > 2 ? 2:extra) != HT_OK) >++ return 0; >++ >++ if (extra > 2) >++ if (PUTBLOCK(me->boundary, extra-2) != HT_OK) >++ return 0; >++ } >++ return seen_nothing(me, b, l); >++} >++ >++/* >++** We're not looking for a delimiter. Look for the next line of input >++** in the data that could potentially be a delimiter. >++*/ >++ >++PRIVATE int seen_nothing(HTStream * me, const char * b, int l) >++{ >++ int i; >++ >++ me->state=seen_nothing; >++ >++ for (i=0; i<l; i++) >++ { >++ if (b[i] != CR) >++ continue; >++ >++ /* >++ ** If we have at least four more characters in unconsumed >++ ** input, and they're not \r\n--, we can safely skip over >++ ** them. >++ */ >++ >++ if (l-i > 4 && >++ strncmp(b+i, "\r\n--", 4)) >++ continue; >++ break; >++ } >++ >++ if (i == 0) >++ { >++ /* Could only be a CR here. */ >++ >++ me->state=seen_cr; >++ return 1; >++ } >++ >++ HTTRACE(STREAM_TRACE, "Boundary: Processed %d (out of %d) bytes\n" >++ _ i _ l); >++ >++ if (PUTBLOCK(b, i) != HT_OK) >++ return 0; >++ >++ return i; >++} >++ >++/* >++** State: seen a CR >++*/ >++ >++PRIVATE int seen_cr(HTStream * me, const char * b, int l) >++{ >++ HTTRACE(STREAM_TRACE, "Boundary: Processed <CR>\n"); >++ >++ if (*b != LF) >++ { >++ HTTRACE(STREAM_TRACE, "Boundary: ... <LF> didn't follow\n"); >++ if (PUTBLOCK("\r", 1) != HT_OK) >++ return 0; >++ return seen_nothing(me, b, l); >++ } >++ >++ HTTRACE(STREAM_TRACE, "Boundary: Processed <CR><LF>\n"); >++ me->state=start_of_line; >++ me->keptcrlf=YES; >++ return 1; >++} >++ >++PRIVATE void process_boundary(HTStream *me, int isterminal) >++{ >++ HTBoundary_flush(me); >++ if (me->target) FREE_TARGET; >++ me->target=NULL; >++ me->state=start_of_line; >++ me->keptcrlf=NO; >++ >++ if (!isterminal) >+ me->target = HTStreamStack(WWW_MIME,me->format, >+ HTMerge(me->orig_target, 2), >+ me->request, YES); >+- if (end > start) { >+- if ((status = PUTBLOCK(start, end-start)) != HT_OK) >+- return status; >+- } >+- } else { >+- if (me->debug) >+- if ((status = PUTDEBUG(start, end-start)) != HT_OK) >+- return status; >+- } >+- start = b; >+- if (*b == '-') me->dash++; >+- me->state = EOL_SLF; >+- } else if (*b == CR) { >+- me->state = EOL_FCR; >+- end = b; >+- } else if (*b == LF) { >+- if (me->state != EOL_FCR) end = b; >+- me->state = EOL_FLF; >+- } >+- b++; >+- } >+- return (start<b && me->body) ? PUTBLOCK(start, b-start) : HT_OK; >+ } >+ >++ >+ PRIVATE int HTBoundary_put_string (HTStream * me, const char * s) >+ { >+ return HTBoundary_put_block(me, s, (int) strlen(s)); >+@@ -133,6 +427,8 @@ PRIVATE int HTBoundary_put_character (HT >+ >+ PRIVATE int HTBoundary_flush (HTStream * me) >+ { >++ if (me->target == NULL) >++ return HT_OK; >+ return (*me->target->isa->flush)(me->target); >+ } >+ >+@@ -182,18 +478,26 @@ PUBLIC HTStream * HTBoundary (HTReques >+ HTResponse_formatParam(response) : >+ HTAnchor_formatParam(anchor); >+ char * boundary = HTAssocList_findObject(type_param, "boundary"); >++ >++ UNUSED(param); >++ UNUSED(input_format); >++ >+ if (boundary) { >+ HTStream * me; >+ if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL) >+ HT_OUTOFMEM("HTBoundary"); >+ me->isa = &HTBoundaryClass; >++ me->net = HTRequest_net(request); >+ me->request = request; >+ me->format = output_format; >+ me->orig_target = output_stream; >+ me->debug = HTRequest_debugStream(request); >+- me->state = EOL_FLF; >++ >++ me->state = start_of_line; >++ me->keptcrlf=NO; >++ >+ StrAllocCopy(me->boundary, boundary); /* Local copy */ >+- me->bpos = me->boundary; >++ >+ HTTRACE(STREAM_TRACE, "Boundary.... Stream created with boundary '%s\'\n" _ me->boundary); >+ return me; >+ } else { > >Property changes on: files/patch-Library_src_HTBound.c >___________________________________________________________________ >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Index: files/patch-configure >=================================================================== >--- files/patch-configure (revision 426176) >+++ files/patch-configure (working copy) >@@ -1,6 +1,6 @@ >---- configure.orig Wed Jun 12 11:31:31 2002 >-+++ configure Sat Mar 10 21:51:00 2007 >-@@ -7612,8 +7612,11 @@ >+--- configure.orig 2002-06-12 09:31:31 UTC >++++ configure >+@@ -7612,8 +7612,11 @@ if test "${with_ssl+set}" = set; then > if test "x$withval" = "xyes"; then > withval=$ssllib > SSLINC=$sslinc >Index: files/patch-libwww-config.in >=================================================================== >--- files/patch-libwww-config.in (revision 426176) >+++ files/patch-libwww-config.in (working copy) >@@ -1,6 +1,6 @@ >---- libwww-config.in.orig Thu Jul 6 18:48:21 2006 >-+++ libwww-config.in Thu Jul 6 18:49:01 2006 >-@@ -48,7 +48,7 @@ >+--- libwww-config.in.orig 1999-06-23 18:05:01 UTC >++++ libwww-config.in >+@@ -48,7 +48,7 @@ while test $# -gt 0; do > echo -I@includedir@ -I@includedir@/@PACKAGE@ @DEFS@ > ;; > --libs) >@@ -9,4 +9,3 @@ > ;; > *) > echo "${usage}" 1>&2 >- >Index: files/patch-modules_expat_xmlparse_xmlparse.c >=================================================================== >--- files/patch-modules_expat_xmlparse_xmlparse.c (nonexistent) >+++ files/patch-modules_expat_xmlparse_xmlparse.c (working copy) >@@ -0,0 +1,16 @@ >+# $FreeBSD$ >+ >+# CVE-2009-3560 >+ >+--- modules/expat/xmlparse/xmlparse.c.orig 2000-08-28 08:52:01 UTC >++++ modules/expat/xmlparse/xmlparse.c >+@@ -2199,6 +2199,9 @@ doProlog(XML_Parser parser, >+ return XML_ERROR_UNCLOSED_TOKEN; >+ case XML_TOK_PARTIAL_CHAR: >+ return XML_ERROR_PARTIAL_CHAR; >++ case -XML_TOK_PROLOG_S: >++ tok = -tok; >++ break; >+ case XML_TOK_NONE: >+ #ifdef XML_DTD >+ if (enc != encoding) > >Property changes on: files/patch-modules_expat_xmlparse_xmlparse.c >___________________________________________________________________ >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property >Index: files/patch-modules_expat_xmltok_xmltok__impl.c >=================================================================== >--- files/patch-modules_expat_xmltok_xmltok__impl.c (nonexistent) >+++ files/patch-modules_expat_xmltok_xmltok__impl.c (working copy) >@@ -0,0 +1,15 @@ >+# $FreeBSD$ >+ >+# CVE-2009-3720 >+ >+--- modules/expat/xmltok/xmltok_impl.c.orig 2000-08-28 08:52:01 UTC >++++ modules/expat/xmltok/xmltok_impl.c >+@@ -1753,7 +1753,7 @@ void PREFIX(updatePosition)(const ENCODI >+ const char *end, >+ POSITION *pos) >+ { >+- while (ptr != end) { >++ while (ptr < end) { >+ switch (BYTE_TYPE(enc, ptr)) { >+ #define LEAD_CASE(n) \ >+ case BT_LEAD ## n: \ > >Property changes on: files/patch-modules_expat_xmltok_xmltok__impl.c >___________________________________________________________________ >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property
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 214546
: 177035