components/libxml2/patches/libxml2-Detect-excessive-entities-expansion-upon-replacement.patch
changeset 1215 88865ad5f165
equal deleted inserted replaced
1214:572261eab84d 1215:88865ad5f165
       
     1 https://git.gnome.org/browse/libxml2/commit/?id=23f05e0c33987d6605387b300c4be5da2120a7ab
       
     2 CVE-2013-0338
       
     3 
       
     4 From 23f05e0c33987d6605387b300c4be5da2120a7ab Mon Sep 17 00:00:00 2001
       
     5 From: Daniel Veillard <[email protected]>
       
     6 Date: Tue, 19 Feb 2013 02:21:49 +0000
       
     7 Subject: Detect excessive entities expansion upon replacement
       
     8 
       
     9 If entities expansion in the XML parser is asked for,
       
    10 it is possble to craft relatively small input document leading
       
    11 to excessive on-the-fly content generation.
       
    12 This patch accounts for those replacement and stop parsing
       
    13 after a given threshold. it can be bypassed as usual with the
       
    14 HUGE parser option.
       
    15 ---
       
    16 diff --git a/include/libxml/parser.h b/include/libxml/parser.h
       
    17 index e1346e4..3f5730d 100644
       
    18 --- a/include/libxml/parser.h
       
    19 +++ b/include/libxml/parser.h
       
    20 @@ -310,6 +310,7 @@ struct _xmlParserCtxt {
       
    21      xmlParserNodeInfo *nodeInfoTab;   /* array of nodeInfos */
       
    22  
       
    23      int                input_id;      /* we need to label inputs */
       
    24 +    unsigned long      sizeentcopy;   /* volume of entity copy */
       
    25  };
       
    26  
       
    27  /**
       
    28 diff --git a/parser.c b/parser.c
       
    29 index 91f8c90..ddf3b5b 100644
       
    30 --- a/parser.c
       
    31 +++ b/parser.c
       
    32 @@ -122,7 +122,7 @@ xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
       
    33   */
       
    34  static int
       
    35  xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
       
    36 -                     xmlEntityPtr ent)
       
    37 +                     xmlEntityPtr ent, size_t replacement)
       
    38  {
       
    39      size_t consumed = 0;
       
    40  
       
    41 @@ -130,7 +130,24 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
       
    42          return (0);
       
    43      if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
       
    44          return (1);
       
    45 -    if (size != 0) {
       
    46 +    if (replacement != 0) {
       
    47 +	if (replacement < XML_MAX_TEXT_LENGTH)
       
    48 +	    return(0);
       
    49 +
       
    50 +        /*
       
    51 +	 * If the volume of entity copy reaches 10 times the
       
    52 +	 * amount of parsed data and over the large text threshold
       
    53 +	 * then that's very likely to be an abuse.
       
    54 +	 */
       
    55 +        if (ctxt->input != NULL) {
       
    56 +	    consumed = ctxt->input->consumed +
       
    57 +	               (ctxt->input->cur - ctxt->input->base);
       
    58 +	}
       
    59 +        consumed += ctxt->sizeentities;
       
    60 +
       
    61 +        if (replacement < XML_PARSER_NON_LINEAR * consumed)
       
    62 +	    return(0);
       
    63 +    } else if (size != 0) {
       
    64          /*
       
    65           * Do the check based on the replacement size of the entity
       
    66           */
       
    67 @@ -176,7 +193,6 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
       
    68           */
       
    69          return (0);
       
    70      }
       
    71 -
       
    72      xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
       
    73      return (1);
       
    74  }
       
    75 @@ -2743,7 +2759,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
       
    76  		    while (*current != 0) { /* non input consuming loop */
       
    77  			buffer[nbchars++] = *current++;
       
    78  			if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
       
    79 -			    if (xmlParserEntityCheck(ctxt, nbchars, ent))
       
    80 +			    if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
       
    81  				goto int_error;
       
    82  			    growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
       
    83  			}
       
    84 @@ -2785,7 +2801,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
       
    85  		    while (*current != 0) { /* non input consuming loop */
       
    86  			buffer[nbchars++] = *current++;
       
    87  			if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
       
    88 -			    if (xmlParserEntityCheck(ctxt, nbchars, ent))
       
    89 +			    if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
       
    90  			        goto int_error;
       
    91  			    growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
       
    92  			}
       
    93 @@ -7203,7 +7219,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
       
    94  	    xmlFreeNodeList(list);
       
    95  	    return;
       
    96  	}
       
    97 -	if (xmlParserEntityCheck(ctxt, 0, ent)) {
       
    98 +	if (xmlParserEntityCheck(ctxt, 0, ent, 0)) {
       
    99  	    xmlFreeNodeList(list);
       
   100  	    return;
       
   101  	}
       
   102 @@ -7361,6 +7377,13 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
       
   103  		xmlNodePtr nw = NULL, cur, firstChild = NULL;
       
   104  
       
   105  		/*
       
   106 +		 * We are copying here, make sure there is no abuse
       
   107 +		 */
       
   108 +		ctxt->sizeentcopy += ent->length;
       
   109 +		if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
       
   110 +		    return;
       
   111 +
       
   112 +		/*
       
   113  		 * when operating on a reader, the entities definitions
       
   114  		 * are always owning the entities subtree.
       
   115  		if (ctxt->parseMode == XML_PARSE_READER)
       
   116 @@ -7400,6 +7423,14 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
       
   117  	    } else if ((list == NULL) || (ctxt->inputNr > 0)) {
       
   118  		xmlNodePtr nw = NULL, cur, next, last,
       
   119  			   firstChild = NULL;
       
   120 +
       
   121 +		/*
       
   122 +		 * We are copying here, make sure there is no abuse
       
   123 +		 */
       
   124 +		ctxt->sizeentcopy += ent->length;
       
   125 +		if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
       
   126 +		    return;
       
   127 +
       
   128  		/*
       
   129  		 * Copy the entity child list and make it the new
       
   130  		 * entity child list. The goal is to make sure any
       
   131 @@ -14767,6 +14798,7 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
       
   132      ctxt->catalogs = NULL;
       
   133      ctxt->nbentities = 0;
       
   134      ctxt->sizeentities = 0;
       
   135 +    ctxt->sizeentcopy = 0;
       
   136      xmlInitNodeInfoSeq(&ctxt->node_seq);
       
   137  
       
   138      if (ctxt->attsDefault != NULL) {
       
   139 diff --git a/parserInternals.c b/parserInternals.c
       
   140 index 02032d5..f8a7041 100644
       
   141 --- a/parserInternals.c
       
   142 +++ b/parserInternals.c
       
   143 @@ -1719,6 +1719,8 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
       
   144      ctxt->charset = XML_CHAR_ENCODING_UTF8;
       
   145      ctxt->catalogs = NULL;
       
   146      ctxt->nbentities = 0;
       
   147 +    ctxt->sizeentities = 0;
       
   148 +    ctxt->sizeentcopy = 0;
       
   149      ctxt->input_id = 1;
       
   150      xmlInitNodeInfoSeq(&ctxt->node_seq);
       
   151      return(0);
       
   152 --
       
   153 cgit v0.9.1