~ubuntu-branches/ubuntu/lucid/libxml2/lucid-updates

« back to all changes in this revision

Viewing changes to parser.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2014-10-22 14:27:25 UTC
  • Revision ID: package-import@ubuntu.com-20141022142725-449j4fkzdfrv26dp
Tags: 2.7.6.dfsg-1ubuntu1.15
* SECURITY UPDATE: denial of service via entity expansion
  - parser.c, SAX2.c, include/libxml/entities.h: refactor entity checking
    and add additional tests.
  - https://git.gnome.org/browse/libxml2/commit/?id=a3f1e3e5712257fd279917a9158278534e8f4b72
  - https://git.gnome.org/browse/libxml2/commit/?id=cff2546f13503ac028e4c1f63c7b6d85f2f2d777
  - https://git.gnome.org/browse/libxml2/commit/?id=be2a7edaf289c5da74a4f9ed3a0b6c733e775230
  - CVE-2014-3660

Show diffs side-by-side

added added

removed removed

Lines of Context:
124
124
        return (0);
125
125
    if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
126
126
        return (1);
 
127
 
 
128
    /*
 
129
     * This may look absurd but is needed to detect
 
130
     * entities problems
 
131
     */
 
132
    if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
 
133
        (ent->content != NULL) && (ent->checked == 0)) {
 
134
        unsigned long oldnbent = ctxt->nbentities;
 
135
        xmlChar *rep;
 
136
 
 
137
        ent->checked = 1;
 
138
 
 
139
        rep = xmlStringDecodeEntities(ctxt, ent->content,
 
140
                                  XML_SUBSTITUTE_REF, 0, 0, 0);
 
141
 
 
142
        ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
 
143
        if (rep != NULL) {
 
144
            if (xmlStrchr(rep, '<'))
 
145
                ent->checked |= 1;
 
146
            xmlFree(rep);
 
147
            rep = NULL;
 
148
        }
 
149
    }
127
150
    if (replacement != 0) {
128
151
        if (replacement < XML_MAX_TEXT_LENGTH)
129
152
            return(0);
164
187
        /*
165
188
         * use the number of parsed entities in the replacement
166
189
         */
167
 
        size = ent->checked;
 
190
        size = ent->checked / 2;
168
191
 
169
192
        /*
170
193
         * The amount of data parsed counting entities size only once
183
206
            return (0);
184
207
    } else {
185
208
        /*
186
 
         * strange we got no data for checking just return
 
209
         * strange we got no data for checking
187
210
         */
188
 
        return (0);
 
211
        if (((ctxt->lastError.code != XML_ERR_UNDECLARED_ENTITY) &&
 
212
             (ctxt->lastError.code != XML_WAR_UNDECLARED_ENTITY)) ||
 
213
            (ctxt->nbentities <= 10000))
 
214
            return (0);
189
215
    }
190
216
    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
191
217
    return (1);
2418
2444
                                      name, NULL);
2419
2445
                    ctxt->valid = 0;
2420
2446
                }
 
2447
                xmlParserEntityCheck(ctxt, 0, NULL, 0);
2421
2448
            } else if (ctxt->input->free != deallocblankswrapper) {
2422
2449
                    input = xmlNewBlanksWrapperInputStream(ctxt, entity);
2423
2450
                    if (xmlPushInput(ctxt, input) < 0)
2588
2615
            if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
2589
2616
                (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
2590
2617
                goto int_error;
 
2618
            xmlParserEntityCheck(ctxt, 0, ent, 0);
2591
2619
            if (ent != NULL)
2592
 
                ctxt->nbentities += ent->checked;
 
2620
                ctxt->nbentities += ent->checked / 2;
2593
2621
            if ((ent != NULL) &&
2594
2622
                (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2595
2623
                if (ent->content != NULL) {
2639
2667
            ent = xmlParseStringPEReference(ctxt, &str);
2640
2668
            if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
2641
2669
                goto int_error;
 
2670
            xmlParserEntityCheck(ctxt, 0, ent, 0);
2642
2671
            if (ent != NULL)
2643
 
                ctxt->nbentities += ent->checked;
 
2672
                ctxt->nbentities += ent->checked / 2;
2644
2673
            if (ent != NULL) {
2645
2674
                if (ent->content == NULL) {
2646
2675
                    xmlLoadEntityContent(ctxt, ent);
3818
3847
                     * entities problems
3819
3848
                     */
3820
3849
                    if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
3821
 
                        (ent->content != NULL)) {
 
3850
                        (ent->content != NULL) && (ent->checked == 0)) {
 
3851
                        unsigned long oldnbent = ctxt->nbentities;
 
3852
 
3822
3853
                        rep = xmlStringDecodeEntities(ctxt, ent->content,
3823
3854
                                                  XML_SUBSTITUTE_REF, 0, 0, 0);
 
3855
 
 
3856
                        ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
3824
3857
                        if (rep != NULL) {
 
3858
                            if (xmlStrchr(rep, '<'))
 
3859
                                ent->checked |= 1;
3825
3860
                            xmlFree(rep);
3826
3861
                            rep = NULL;
3827
3862
                        }
6941
6976
         * Store the number of entities needing parsing for this entity
6942
6977
         * content and do checkings
6943
6978
         */
6944
 
        ent->checked = ctxt->nbentities - oldnbent;
 
6979
        ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
 
6980
        if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
 
6981
            ent->checked |= 1;
6945
6982
        if (ret == XML_ERR_ENTITY_LOOP) {
6946
6983
            xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
6947
6984
            xmlFreeNodeList(list);
7000
7037
                   (ret != XML_WAR_UNDECLARED_ENTITY)) {
7001
7038
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7002
7039
                     "Entity '%s' failed to parse\n", ent->name);
 
7040
            xmlParserEntityCheck(ctxt, 0, ent, 0);
7003
7041
        } else if (list != NULL) {
7004
7042
            xmlFreeNodeList(list);
7005
7043
            list = NULL;
7006
7044
        }
7007
7045
        if (ent->checked == 0)
7008
 
            ent->checked = 1;
 
7046
            ent->checked = 2;
7009
7047
    } else if (ent->checked != 1) {
7010
 
        ctxt->nbentities += ent->checked;
 
7048
        ctxt->nbentities += ent->checked / 2;
7011
7049
    }
7012
7050
 
7013
7051
    /*
7108
7146
                /*
7109
7147
                 * We are copying here, make sure there is no abuse
7110
7148
                 */
7111
 
                ctxt->sizeentcopy += ent->length;
 
7149
                ctxt->sizeentcopy += ent->length + 5;
7112
7150
                if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7113
7151
                    return;
7114
7152
 
7156
7194
                /*
7157
7195
                 * We are copying here, make sure there is no abuse
7158
7196
                 */
7159
 
                ctxt->sizeentcopy += ent->length;
 
7197
                ctxt->sizeentcopy += ent->length + 5;
7160
7198
                if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7161
7199
                    return;
7162
7200
 
7342
7380
                ctxt->sax->reference(ctxt->userData, name);
7343
7381
            }
7344
7382
        }
 
7383
        xmlParserEntityCheck(ctxt, 0, ent, 0);
7345
7384
        ctxt->valid = 0;
7346
7385
    }
7347
7386
 
7372
7411
     * not contain a <. 
7373
7412
     */
7374
7413
    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7375
 
             (ent != NULL) && (ent->content != NULL) &&
7376
 
             (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
7377
 
             (xmlStrchr(ent->content, '<'))) {
7378
 
        xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7379
 
    "'<' in entity '%s' is not allowed in attributes values\n", name);
 
7414
             (ent != NULL) && 
 
7415
             (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
 
7416
        if ((ent->checked & 1) || ((ent->checked == 0) &&
 
7417
             (ent->content != NULL) &&(xmlStrchr(ent->content, '<')))) {
 
7418
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
 
7419
        "'<' in entity '%s' is not allowed in attributes values\n", name);
 
7420
        }
7380
7421
    }
7381
7422
 
7382
7423
    /*
7533
7574
                          "Entity '%s' not defined\n",
7534
7575
                          name);
7535
7576
        }
 
7577
        xmlParserEntityCheck(ctxt, 0, ent, 0);
7536
7578
        /* TODO ? check regressions ctxt->valid = 0; */
7537
7579
    }
7538
7580
 
7692
7734
                          name, NULL);
7693
7735
            ctxt->valid = 0;
7694
7736
        }
 
7737
        xmlParserEntityCheck(ctxt, 0, NULL, 0);
7695
7738
    } else {
7696
7739
        /*
7697
7740
         * Internal checking in case the entity quest barfed
7922
7965
                          name, NULL);
7923
7966
            ctxt->valid = 0;
7924
7967
        }
 
7968
        xmlParserEntityCheck(ctxt, 0, NULL, 0);
7925
7969
    } else {
7926
7970
        /*
7927
7971
         * Internal checking in case the entity quest barfed