src/lib/expat/xmlparse.c
| r15669 | r15670 | |
| 5 | 5 | #include <stddef.h> |
| 6 | 6 | #include <string.h> /* memset(), memcpy() */ |
| 7 | 7 | #include <assert.h> |
| 8 | #include <limits.h> /* UINT_MAX */ |
| 9 | #include <time.h> /* time() */ |
| 8 | 10 | |
| 9 | 11 | #define XML_BUILDING_EXPAT 1 |
| 10 | 12 | |
| r15669 | r15670 | |
| 381 | 383 | static void |
| 382 | 384 | dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms); |
| 383 | 385 | static int |
| 384 | | dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms); |
| 386 | dtdCopy(XML_Parser oldParser, |
| 387 | DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms); |
| 385 | 388 | static int |
| 386 | | copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *); |
| 387 | | |
| 389 | copyEntityTable(XML_Parser oldParser, |
| 390 | HASH_TABLE *, STRING_POOL *, const HASH_TABLE *); |
| 388 | 391 | static NAMED * |
| 389 | | lookup(HASH_TABLE *table, KEY name, size_t createSize); |
| 392 | lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize); |
| 390 | 393 | static void FASTCALL |
| 391 | 394 | hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms); |
| 392 | 395 | static void FASTCALL hashTableClear(HASH_TABLE *); |
| r15669 | r15670 | |
| 419 | 422 | getElementType(XML_Parser parser, const ENCODING *enc, |
| 420 | 423 | const char *ptr, const char *end); |
| 421 | 424 | |
| 425 | static unsigned long generate_hash_secret_salt(void); |
| 426 | static XML_Bool startParsing(XML_Parser parser); |
| 427 | |
| 422 | 428 | static XML_Parser |
| 423 | 429 | parserCreate(const XML_Char *encodingName, |
| 424 | 430 | const XML_Memory_Handling_Suite *memsuite, |
| 425 | 431 | const XML_Char *nameSep, |
| 426 | 432 | DTD *dtd); |
| 433 | |
| 427 | 434 | static void |
| 428 | 435 | parserInit(XML_Parser parser, const XML_Char *encodingName); |
| 429 | 436 | |
| r15669 | r15670 | |
| 523 | 530 | NS_ATT *m_nsAtts; |
| 524 | 531 | unsigned long m_nsAttsVersion; |
| 525 | 532 | unsigned char m_nsAttsPower; |
| 533 | #ifdef XML_ATTR_INFO |
| 534 | XML_AttrInfo *m_attInfo; |
| 535 | #endif |
| 526 | 536 | POSITION m_position; |
| 527 | 537 | STRING_POOL m_tempPool; |
| 528 | 538 | STRING_POOL m_temp2Pool; |
| r15669 | r15670 | |
| 536 | 546 | XML_Bool m_useForeignDTD; |
| 537 | 547 | enum XML_ParamEntityParsing m_paramEntityParsing; |
| 538 | 548 | #endif |
| 549 | unsigned long m_hash_secret_salt; |
| 539 | 550 | }; |
| 540 | 551 | |
| 541 | 552 | #define MALLOC(s) (parser->m_mem.malloc_fcn((s))) |
| r15669 | r15670 | |
| 630 | 641 | #define nsAtts (parser->m_nsAtts) |
| 631 | 642 | #define nsAttsVersion (parser->m_nsAttsVersion) |
| 632 | 643 | #define nsAttsPower (parser->m_nsAttsPower) |
| 644 | #define attInfo (parser->m_attInfo) |
| 633 | 645 | #define tempPool (parser->m_tempPool) |
| 634 | 646 | #define temp2Pool (parser->m_temp2Pool) |
| 635 | 647 | #define groupConnector (parser->m_groupConnector) |
| r15669 | r15670 | |
| 643 | 655 | #define useForeignDTD (parser->m_useForeignDTD) |
| 644 | 656 | #define paramEntityParsing (parser->m_paramEntityParsing) |
| 645 | 657 | #endif /* XML_DTD */ |
| 658 | #define hash_secret_salt (parser->m_hash_secret_salt) |
| 646 | 659 | |
| 647 | 660 | XML_Parser XMLCALL |
| 648 | 661 | XML_ParserCreate(const XML_Char *encodingName) |
| r15669 | r15670 | |
| 667 | 680 | ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0' |
| 668 | 681 | }; |
| 669 | 682 | |
| 670 | | XML_Parser XMLCALL |
| 671 | | XML_ParserCreate_MM(const XML_Char *encodingName, |
| 672 | | const XML_Memory_Handling_Suite *memsuite, |
| 673 | | const XML_Char *nameSep) |
| 683 | static unsigned long |
| 684 | generate_hash_secret_salt(void) |
| 674 | 685 | { |
| 675 | | XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL); |
| 676 | | if (parser != NULL && ns) { |
| 686 | unsigned int seed = time(NULL) % UINT_MAX; |
| 687 | srand(seed); |
| 688 | return rand(); |
| 689 | } |
| 690 | |
| 691 | static XML_Bool /* only valid for root parser */ |
| 692 | startParsing(XML_Parser parser) |
| 693 | { |
| 694 | /* hash functions must be initialized before setContext() is called */ |
| 695 | if (hash_secret_salt == 0) |
| 696 | hash_secret_salt = generate_hash_secret_salt(); |
| 697 | if (ns) { |
| 677 | 698 | /* implicit context only set for root parser, since child |
| 678 | 699 | parsers (i.e. external entity parsers) will inherit it |
| 679 | 700 | */ |
| 680 | | if (!setContext(parser, implicitContext)) { |
| 681 | | XML_ParserFree(parser); |
| 682 | | return NULL; |
| 701 | return setContext(parser, implicitContext); |
| 683 | 702 | } |
| 703 | return XML_TRUE; |
| 684 | 704 | } |
| 685 | | return parser; |
| 705 | |
| 706 | XML_Parser XMLCALL |
| 707 | XML_ParserCreate_MM(const XML_Char *encodingName, |
| 708 | const XML_Memory_Handling_Suite *memsuite, |
| 709 | const XML_Char *nameSep) |
| 710 | { |
| 711 | return parserCreate(encodingName, memsuite, nameSep, NULL); |
| 686 | 712 | } |
| 687 | 713 | |
| 688 | 714 | static XML_Parser |
| r15669 | r15670 | |
| 727 | 753 | FREE(parser); |
| 728 | 754 | return NULL; |
| 729 | 755 | } |
| 756 | #ifdef XML_ATTR_INFO |
| 757 | attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo)); |
| 758 | if (attInfo == NULL) { |
| 759 | FREE(atts); |
| 760 | FREE(parser); |
| 761 | return NULL; |
| 762 | } |
| 763 | #endif |
| 730 | 764 | dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); |
| 731 | 765 | if (dataBuf == NULL) { |
| 732 | 766 | FREE(atts); |
| 767 | #ifdef XML_ATTR_INFO |
| 768 | FREE(attInfo); |
| 769 | #endif |
| 733 | 770 | FREE(parser); |
| 734 | 771 | return NULL; |
| 735 | 772 | } |
| r15669 | r15670 | |
| 742 | 779 | if (_dtd == NULL) { |
| 743 | 780 | FREE(dataBuf); |
| 744 | 781 | FREE(atts); |
| 782 | #ifdef XML_ATTR_INFO |
| 783 | FREE(attInfo); |
| 784 | #endif |
| 745 | 785 | FREE(parser); |
| 746 | 786 | return NULL; |
| 747 | 787 | } |
| r15669 | r15670 | |
| 856 | 896 | useForeignDTD = XML_FALSE; |
| 857 | 897 | paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; |
| 858 | 898 | #endif |
| 899 | hash_secret_salt = 0; |
| 859 | 900 | } |
| 860 | 901 | |
| 861 | 902 | /* moves list of bindings to freeBindingList */ |
| r15669 | r15670 | |
| 903 | 944 | poolClear(&temp2Pool); |
| 904 | 945 | parserInit(parser, encodingName); |
| 905 | 946 | dtdReset(_dtd, &parser->m_mem); |
| 906 | | return setContext(parser, implicitContext); |
| 947 | return XML_TRUE; |
| 907 | 948 | } |
| 908 | 949 | |
| 909 | 950 | enum XML_Status XMLCALL |
| r15669 | r15670 | |
| 972 | 1013 | int oldInEntityValue = prologState.inEntityValue; |
| 973 | 1014 | #endif |
| 974 | 1015 | XML_Bool oldns_triplets = ns_triplets; |
| 1016 | /* Note that the new parser shares the same hash secret as the old |
| 1017 | parser, so that dtdCopy and copyEntityTable can lookup values |
| 1018 | from hash tables associated with either parser without us having |
| 1019 | to worry which hash secrets each table has. |
| 1020 | */ |
| 1021 | unsigned long oldhash_secret_salt = hash_secret_salt; |
| 975 | 1022 | |
| 976 | 1023 | #ifdef XML_DTD |
| 977 | 1024 | if (!context) |
| r15669 | r15670 | |
| 1025 | 1072 | externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; |
| 1026 | 1073 | defaultExpandInternalEntities = oldDefaultExpandInternalEntities; |
| 1027 | 1074 | ns_triplets = oldns_triplets; |
| 1075 | hash_secret_salt = oldhash_secret_salt; |
| 1028 | 1076 | parentParser = oldParser; |
| 1029 | 1077 | #ifdef XML_DTD |
| 1030 | 1078 | paramEntityParsing = oldParamEntityParsing; |
| 1031 | 1079 | prologState.inEntityValue = oldInEntityValue; |
| 1032 | 1080 | if (context) { |
| 1033 | 1081 | #endif /* XML_DTD */ |
| 1034 | | if (!dtdCopy(_dtd, oldDtd, &parser->m_mem) |
| 1082 | if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem) |
| 1035 | 1083 | || !setContext(parser, context)) { |
| 1036 | 1084 | XML_ParserFree(parser); |
| 1037 | 1085 | return NULL; |
| r15669 | r15670 | |
| 1120 | 1168 | #endif /* XML_DTD */ |
| 1121 | 1169 | dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem); |
| 1122 | 1170 | FREE((void *)atts); |
| 1171 | #ifdef XML_ATTR_INFO |
| 1172 | FREE((void *)attInfo); |
| 1173 | #endif |
| 1123 | 1174 | FREE(groupConnector); |
| 1124 | 1175 | FREE(buffer); |
| 1125 | 1176 | FREE(dataBuf); |
| r15669 | r15670 | |
| 1200 | 1251 | return idAttIndex; |
| 1201 | 1252 | } |
| 1202 | 1253 | |
| 1254 | #ifdef XML_ATTR_INFO |
| 1255 | const XML_AttrInfo * XMLCALL |
| 1256 | XML_GetAttributeInfo(XML_Parser parser) |
| 1257 | { |
| 1258 | return attInfo; |
| 1259 | } |
| 1260 | #endif |
| 1261 | |
| 1203 | 1262 | void XMLCALL |
| 1204 | 1263 | XML_SetElementHandler(XML_Parser parser, |
| 1205 | 1264 | XML_StartElementHandler start, |
| r15669 | r15670 | |
| 1416 | 1475 | #endif |
| 1417 | 1476 | } |
| 1418 | 1477 | |
| 1478 | int XMLCALL |
| 1479 | XML_SetHashSalt(XML_Parser parser, |
| 1480 | unsigned long hash_salt) |
| 1481 | { |
| 1482 | /* block after XML_Parse()/XML_ParseBuffer() has been called */ |
| 1483 | if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) |
| 1484 | return 0; |
| 1485 | hash_secret_salt = hash_salt; |
| 1486 | return 1; |
| 1487 | } |
| 1488 | |
| 1419 | 1489 | enum XML_Status XMLCALL |
| 1420 | 1490 | XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) |
| 1421 | 1491 | { |
| r15669 | r15670 | |
| 1426 | 1496 | case XML_FINISHED: |
| 1427 | 1497 | errorCode = XML_ERROR_FINISHED; |
| 1428 | 1498 | return XML_STATUS_ERROR; |
| 1499 | case XML_INITIALIZED: |
| 1500 | if (parentParser == NULL && !startParsing(parser)) { |
| 1501 | errorCode = XML_ERROR_NO_MEMORY; |
| 1502 | return XML_STATUS_ERROR; |
| 1503 | } |
| 1429 | 1504 | default: |
| 1430 | 1505 | ps_parsing = XML_PARSING; |
| 1431 | 1506 | } |
| r15669 | r15670 | |
| 1484 | 1559 | break; |
| 1485 | 1560 | case XML_INITIALIZED: |
| 1486 | 1561 | case XML_PARSING: |
| 1487 | | result = XML_STATUS_OK; |
| 1488 | 1562 | if (isFinal) { |
| 1489 | 1563 | ps_parsing = XML_FINISHED; |
| 1490 | | return result; |
| 1564 | return XML_STATUS_OK; |
| 1491 | 1565 | } |
| 1566 | /* fall through */ |
| 1567 | default: |
| 1568 | result = XML_STATUS_OK; |
| 1492 | 1569 | } |
| 1493 | 1570 | } |
| 1494 | 1571 | |
| r15669 | r15670 | |
| 1503 | 1580 | : (char *)REALLOC(buffer, len * 2)); |
| 1504 | 1581 | if (temp == NULL) { |
| 1505 | 1582 | errorCode = XML_ERROR_NO_MEMORY; |
| 1506 | | return XML_STATUS_ERROR; |
| 1507 | | } |
| 1508 | | buffer = temp; |
| 1509 | | if (!buffer) { |
| 1510 | | errorCode = XML_ERROR_NO_MEMORY; |
| 1511 | 1583 | eventPtr = eventEndPtr = NULL; |
| 1512 | 1584 | processor = errorProcessor; |
| 1513 | 1585 | return XML_STATUS_ERROR; |
| 1514 | 1586 | } |
| 1587 | buffer = temp; |
| 1515 | 1588 | bufferLim = buffer + len * 2; |
| 1516 | 1589 | } |
| 1517 | 1590 | memcpy(buffer, end, nLeftOver); |
| r15669 | r15670 | |
| 1549 | 1622 | case XML_FINISHED: |
| 1550 | 1623 | errorCode = XML_ERROR_FINISHED; |
| 1551 | 1624 | return XML_STATUS_ERROR; |
| 1625 | case XML_INITIALIZED: |
| 1626 | if (parentParser == NULL && !startParsing(parser)) { |
| 1627 | errorCode = XML_ERROR_NO_MEMORY; |
| 1628 | return XML_STATUS_ERROR; |
| 1629 | } |
| 1552 | 1630 | default: |
| 1553 | 1631 | ps_parsing = XML_PARSING; |
| 1554 | 1632 | } |
| r15669 | r15670 | |
| 1662 | 1740 | bufferPtr = buffer = newBuf; |
| 1663 | 1741 | #endif /* not defined XML_CONTEXT_BYTES */ |
| 1664 | 1742 | } |
| 1743 | eventPtr = eventEndPtr = NULL; |
| 1744 | positionPtr = NULL; |
| 1665 | 1745 | } |
| 1666 | 1746 | return bufferEnd; |
| 1667 | 1747 | } |
| r15669 | r15670 | |
| 1947 | 2027 | #ifdef XML_LARGE_SIZE |
| 1948 | 2028 | {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0}, |
| 1949 | 2029 | #endif |
| 2030 | #ifdef XML_ATTR_INFO |
| 2031 | {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0}, |
| 2032 | #endif |
| 1950 | 2033 | {XML_FEATURE_END, NULL, 0} |
| 1951 | 2034 | }; |
| 1952 | 2035 | |
| r15669 | r15670 | |
| 2230 | 2313 | next - enc->minBytesPerChar); |
| 2231 | 2314 | if (!name) |
| 2232 | 2315 | return XML_ERROR_NO_MEMORY; |
| 2233 | | entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); |
| 2316 | entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0); |
| 2234 | 2317 | poolDiscard(&dtd->pool); |
| 2235 | 2318 | /* First, determine if a check for an existing declaration is needed; |
| 2236 | 2319 | if yes, check that the entity exists, and that it is internal, |
| r15669 | r15670 | |
| 2620 | 2703 | const XML_Char *localPart; |
| 2621 | 2704 | |
| 2622 | 2705 | /* lookup the element type name */ |
| 2623 | | elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0); |
| 2706 | elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0); |
| 2624 | 2707 | if (!elementType) { |
| 2625 | 2708 | const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); |
| 2626 | 2709 | if (!name) |
| 2627 | 2710 | return XML_ERROR_NO_MEMORY; |
| 2628 | | elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name, |
| 2711 | elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name, |
| 2629 | 2712 | sizeof(ELEMENT_TYPE)); |
| 2630 | 2713 | if (!elementType) |
| 2631 | 2714 | return XML_ERROR_NO_MEMORY; |
| r15669 | r15670 | |
| 2639 | 2722 | if (n + nDefaultAtts > attsSize) { |
| 2640 | 2723 | int oldAttsSize = attsSize; |
| 2641 | 2724 | ATTRIBUTE *temp; |
| 2725 | #ifdef XML_ATTR_INFO |
| 2726 | XML_AttrInfo *temp2; |
| 2727 | #endif |
| 2642 | 2728 | attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; |
| 2643 | 2729 | temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE)); |
| 2644 | 2730 | if (temp == NULL) |
| 2645 | 2731 | return XML_ERROR_NO_MEMORY; |
| 2646 | 2732 | atts = temp; |
| 2733 | #ifdef XML_ATTR_INFO |
| 2734 | temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo)); |
| 2735 | if (temp2 == NULL) |
| 2736 | return XML_ERROR_NO_MEMORY; |
| 2737 | attInfo = temp2; |
| 2738 | #endif |
| 2647 | 2739 | if (n > oldAttsSize) |
| 2648 | 2740 | XmlGetAttributes(enc, attStr, n, atts); |
| 2649 | 2741 | } |
| 2650 | 2742 | |
| 2651 | 2743 | appAtts = (const XML_Char **)atts; |
| 2652 | 2744 | for (i = 0; i < n; i++) { |
| 2745 | ATTRIBUTE *currAtt = &atts[i]; |
| 2746 | #ifdef XML_ATTR_INFO |
| 2747 | XML_AttrInfo *currAttInfo = &attInfo[i]; |
| 2748 | #endif |
| 2653 | 2749 | /* add the name and value to the attribute list */ |
| 2654 | | ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, |
| 2655 | | atts[i].name |
| 2656 | | + XmlNameLength(enc, atts[i].name)); |
| 2750 | ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name, |
| 2751 | currAtt->name |
| 2752 | + XmlNameLength(enc, currAtt->name)); |
| 2657 | 2753 | if (!attId) |
| 2658 | 2754 | return XML_ERROR_NO_MEMORY; |
| 2755 | #ifdef XML_ATTR_INFO |
| 2756 | currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name); |
| 2757 | currAttInfo->nameEnd = currAttInfo->nameStart + |
| 2758 | XmlNameLength(enc, currAtt->name); |
| 2759 | currAttInfo->valueStart = parseEndByteIndex - |
| 2760 | (parseEndPtr - currAtt->valuePtr); |
| 2761 | currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd); |
| 2762 | #endif |
| 2659 | 2763 | /* Detect duplicate attributes by their QNames. This does not work when |
| 2660 | 2764 | namespace processing is turned on and different prefixes for the same |
| 2661 | 2765 | namespace are used. For this case we have a check further down. |
| r15669 | r15670 | |
| 2794 | 2898 | if (s[-1] == 2) { /* prefixed */ |
| 2795 | 2899 | ATTRIBUTE_ID *id; |
| 2796 | 2900 | const BINDING *b; |
| 2797 | | unsigned long uriHash = 0; |
| 2901 | unsigned long uriHash = hash_secret_salt; |
| 2798 | 2902 | ((XML_Char *)s)[-1] = 0; /* clear flag */ |
| 2799 | | id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0); |
| 2903 | id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0); |
| 2800 | 2904 | b = id->prefix->binding; |
| 2801 | 2905 | if (!b) |
| 2802 | 2906 | return XML_ERROR_UNBOUND_PREFIX; |
| r15669 | r15670 | |
| 2818 | 2922 | } while (*s++); |
| 2819 | 2923 | |
| 2820 | 2924 | { /* Check hash table for duplicate of expanded name (uriName). |
| 2821 | | Derived from code in lookup(HASH_TABLE *table, ...). |
| 2925 | Derived from code in lookup(parser, HASH_TABLE *table, ...). |
| 2822 | 2926 | */ |
| 2823 | 2927 | unsigned char step = 0; |
| 2824 | 2928 | unsigned long mask = nsAttsSize - 1; |
| r15669 | r15670 | |
| 3693 | 3797 | return XML_ERROR_UNCLOSED_TOKEN; |
| 3694 | 3798 | case XML_TOK_PARTIAL_CHAR: |
| 3695 | 3799 | return XML_ERROR_PARTIAL_CHAR; |
| 3800 | case -XML_TOK_PROLOG_S: |
| 3801 | tok = -tok; |
| 3802 | break; |
| 3696 | 3803 | case XML_TOK_NONE: |
| 3697 | 3804 | #ifdef XML_DTD |
| 3698 | 3805 | /* for internal PE NOT referenced between declarations */ |
| r15669 | r15670 | |
| 3764 | 3871 | case XML_ROLE_DOCTYPE_PUBLIC_ID: |
| 3765 | 3872 | #ifdef XML_DTD |
| 3766 | 3873 | useForeignDTD = XML_FALSE; |
| 3767 | | declEntity = (ENTITY *)lookup(&dtd->paramEntities, |
| 3874 | declEntity = (ENTITY *)lookup(parser, |
| 3875 | &dtd->paramEntities, |
| 3768 | 3876 | externalSubsetName, |
| 3769 | 3877 | sizeof(ENTITY)); |
| 3770 | 3878 | if (!declEntity) |
| r15669 | r15670 | |
| 3772 | 3880 | #endif /* XML_DTD */ |
| 3773 | 3881 | dtd->hasParamEntityRefs = XML_TRUE; |
| 3774 | 3882 | if (startDoctypeDeclHandler) { |
| 3883 | XML_Char *pubId; |
| 3775 | 3884 | if (!XmlIsPublicId(enc, s, next, eventPP)) |
| 3776 | 3885 | return XML_ERROR_PUBLICID; |
| 3777 | | doctypePubid = poolStoreString(&tempPool, enc, |
| 3886 | pubId = poolStoreString(&tempPool, enc, |
| 3778 | 3887 | s + enc->minBytesPerChar, |
| 3779 | 3888 | next - enc->minBytesPerChar); |
| 3780 | | if (!doctypePubid) |
| 3889 | if (!pubId) |
| 3781 | 3890 | return XML_ERROR_NO_MEMORY; |
| 3782 | | normalizePublicId((XML_Char *)doctypePubid); |
| 3891 | normalizePublicId(pubId); |
| 3783 | 3892 | poolFinish(&tempPool); |
| 3893 | doctypePubid = pubId; |
| 3784 | 3894 | handleDefault = XML_FALSE; |
| 3785 | 3895 | goto alreadyChecked; |
| 3786 | 3896 | } |
| r15669 | r15670 | |
| 3819 | 3929 | XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; |
| 3820 | 3930 | dtd->hasParamEntityRefs = XML_TRUE; |
| 3821 | 3931 | if (paramEntityParsing && externalEntityRefHandler) { |
| 3822 | | ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, |
| 3932 | ENTITY *entity = (ENTITY *)lookup(parser, |
| 3933 | &dtd->paramEntities, |
| 3823 | 3934 | externalSubsetName, |
| 3824 | 3935 | sizeof(ENTITY)); |
| 3825 | 3936 | if (!entity) |
| r15669 | r15670 | |
| 3863 | 3974 | XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; |
| 3864 | 3975 | dtd->hasParamEntityRefs = XML_TRUE; |
| 3865 | 3976 | if (paramEntityParsing && externalEntityRefHandler) { |
| 3866 | | ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, |
| 3977 | ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities, |
| 3867 | 3978 | externalSubsetName, |
| 3868 | 3979 | sizeof(ENTITY)); |
| 3869 | 3980 | if (!entity) |
| r15669 | r15670 | |
| 4077 | 4188 | break; |
| 4078 | 4189 | #else /* XML_DTD */ |
| 4079 | 4190 | if (!declEntity) { |
| 4080 | | declEntity = (ENTITY *)lookup(&dtd->paramEntities, |
| 4191 | declEntity = (ENTITY *)lookup(parser, |
| 4192 | &dtd->paramEntities, |
| 4081 | 4193 | externalSubsetName, |
| 4082 | 4194 | sizeof(ENTITY)); |
| 4083 | 4195 | if (!declEntity) |
| r15669 | r15670 | |
| 4152 | 4264 | const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); |
| 4153 | 4265 | if (!name) |
| 4154 | 4266 | return XML_ERROR_NO_MEMORY; |
| 4155 | | declEntity = (ENTITY *)lookup(&dtd->generalEntities, name, |
| 4267 | declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, |
| 4156 | 4268 | sizeof(ENTITY)); |
| 4157 | 4269 | if (!declEntity) |
| 4158 | 4270 | return XML_ERROR_NO_MEMORY; |
| r15669 | r15670 | |
| 4184 | 4296 | const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); |
| 4185 | 4297 | if (!name) |
| 4186 | 4298 | return XML_ERROR_NO_MEMORY; |
| 4187 | | declEntity = (ENTITY *)lookup(&dtd->paramEntities, |
| 4299 | declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities, |
| 4188 | 4300 | name, sizeof(ENTITY)); |
| 4189 | 4301 | if (!declEntity) |
| 4190 | 4302 | return XML_ERROR_NO_MEMORY; |
| r15669 | r15670 | |
| 4366 | 4478 | next - enc->minBytesPerChar); |
| 4367 | 4479 | if (!name) |
| 4368 | 4480 | return XML_ERROR_NO_MEMORY; |
| 4369 | | entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); |
| 4481 | entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0); |
| 4370 | 4482 | poolDiscard(&dtd->pool); |
| 4371 | 4483 | /* first, determine if a check for an existing declaration is needed; |
| 4372 | 4484 | if yes, check that the entity exists, and that it is internal, |
| r15669 | r15670 | |
| 4890 | 5002 | next - enc->minBytesPerChar); |
| 4891 | 5003 | if (!name) |
| 4892 | 5004 | return XML_ERROR_NO_MEMORY; |
| 4893 | | entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); |
| 5005 | entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0); |
| 4894 | 5006 | poolDiscard(&temp2Pool); |
| 4895 | 5007 | /* First, determine if a check for an existing declaration is needed; |
| 4896 | 5008 | if yes, check that the entity exists, and that it is internal. |
| r15669 | r15670 | |
| 4999 | 5111 | result = XML_ERROR_NO_MEMORY; |
| 5000 | 5112 | goto endEntityValue; |
| 5001 | 5113 | } |
| 5002 | | entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); |
| 5114 | entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0); |
| 5003 | 5115 | poolDiscard(&tempPool); |
| 5004 | 5116 | if (!entity) { |
| 5005 | 5117 | /* not a well-formedness error - see XML 1.0: WFC Entity Declared */ |
| r15669 | r15670 | |
| 5289 | 5401 | } |
| 5290 | 5402 | if (!poolAppendChar(&dtd->pool, XML_T('\0'))) |
| 5291 | 5403 | return 0; |
| 5292 | | prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), |
| 5404 | prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool), |
| 5293 | 5405 | sizeof(PREFIX)); |
| 5294 | 5406 | if (!prefix) |
| 5295 | 5407 | return 0; |
| r15669 | r15670 | |
| 5318 | 5430 | return NULL; |
| 5319 | 5431 | /* skip quotation mark - its storage will be re-used (like in name[-1]) */ |
| 5320 | 5432 | ++name; |
| 5321 | | id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); |
| 5433 | id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); |
| 5322 | 5434 | if (!id) |
| 5323 | 5435 | return NULL; |
| 5324 | 5436 | if (id->name != name) |
| r15669 | r15670 | |
| 5336 | 5448 | if (name[5] == XML_T('\0')) |
| 5337 | 5449 | id->prefix = &dtd->defaultPrefix; |
| 5338 | 5450 | else |
| 5339 | | id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX)); |
| 5451 | id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX)); |
| 5340 | 5452 | id->xmlns = XML_TRUE; |
| 5341 | 5453 | } |
| 5342 | 5454 | else { |
| r15669 | r15670 | |
| 5351 | 5463 | } |
| 5352 | 5464 | if (!poolAppendChar(&dtd->pool, XML_T('\0'))) |
| 5353 | 5465 | return NULL; |
| 5354 | | id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), |
| 5466 | id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool), |
| 5355 | 5467 | sizeof(PREFIX)); |
| 5356 | 5468 | if (id->prefix->name == poolStart(&dtd->pool)) |
| 5357 | 5469 | poolFinish(&dtd->pool); |
| r15669 | r15670 | |
| 5447 | 5559 | ENTITY *e; |
| 5448 | 5560 | if (!poolAppendChar(&tempPool, XML_T('\0'))) |
| 5449 | 5561 | return XML_FALSE; |
| 5450 | | e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0); |
| 5562 | e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0); |
| 5451 | 5563 | if (e) |
| 5452 | 5564 | e->open = XML_TRUE; |
| 5453 | 5565 | if (*s != XML_T('\0')) |
| r15669 | r15670 | |
| 5462 | 5574 | else { |
| 5463 | 5575 | if (!poolAppendChar(&tempPool, XML_T('\0'))) |
| 5464 | 5576 | return XML_FALSE; |
| 5465 | | prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool), |
| 5577 | prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool), |
| 5466 | 5578 | sizeof(PREFIX)); |
| 5467 | 5579 | if (!prefix) |
| 5468 | 5580 | return XML_FALSE; |
| r15669 | r15670 | |
| 5626 | 5738 | The new DTD has already been initialized. |
| 5627 | 5739 | */ |
| 5628 | 5740 | static int |
| 5629 | | dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) |
| 5741 | dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) |
| 5630 | 5742 | { |
| 5631 | 5743 | HASH_TABLE_ITER iter; |
| 5632 | 5744 | |
| r15669 | r15670 | |
| 5641 | 5753 | name = poolCopyString(&(newDtd->pool), oldP->name); |
| 5642 | 5754 | if (!name) |
| 5643 | 5755 | return 0; |
| 5644 | | if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) |
| 5756 | if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX))) |
| 5645 | 5757 | return 0; |
| 5646 | 5758 | } |
| 5647 | 5759 | |
| r15669 | r15670 | |
| 5663 | 5775 | if (!name) |
| 5664 | 5776 | return 0; |
| 5665 | 5777 | ++name; |
| 5666 | | newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, |
| 5778 | newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name, |
| 5667 | 5779 | sizeof(ATTRIBUTE_ID)); |
| 5668 | 5780 | if (!newA) |
| 5669 | 5781 | return 0; |
| r15669 | r15670 | |
| 5673 | 5785 | if (oldA->prefix == &oldDtd->defaultPrefix) |
| 5674 | 5786 | newA->prefix = &newDtd->defaultPrefix; |
| 5675 | 5787 | else |
| 5676 | | newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), |
| 5788 | newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes), |
| 5677 | 5789 | oldA->prefix->name, 0); |
| 5678 | 5790 | } |
| 5679 | 5791 | } |
| r15669 | r15670 | |
| 5692 | 5804 | name = poolCopyString(&(newDtd->pool), oldE->name); |
| 5693 | 5805 | if (!name) |
| 5694 | 5806 | return 0; |
| 5695 | | newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, |
| 5807 | newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name, |
| 5696 | 5808 | sizeof(ELEMENT_TYPE)); |
| 5697 | 5809 | if (!newE) |
| 5698 | 5810 | return 0; |
| r15669 | r15670 | |
| 5706 | 5818 | } |
| 5707 | 5819 | if (oldE->idAtt) |
| 5708 | 5820 | newE->idAtt = (ATTRIBUTE_ID *) |
| 5709 | | lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0); |
| 5821 | lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0); |
| 5710 | 5822 | newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; |
| 5711 | 5823 | if (oldE->prefix) |
| 5712 | | newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), |
| 5824 | newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes), |
| 5713 | 5825 | oldE->prefix->name, 0); |
| 5714 | 5826 | for (i = 0; i < newE->nDefaultAtts; i++) { |
| 5715 | 5827 | newE->defaultAtts[i].id = (ATTRIBUTE_ID *) |
| 5716 | | lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); |
| 5828 | lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); |
| 5717 | 5829 | newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; |
| 5718 | 5830 | if (oldE->defaultAtts[i].value) { |
| 5719 | 5831 | newE->defaultAtts[i].value |
| r15669 | r15670 | |
| 5727 | 5839 | } |
| 5728 | 5840 | |
| 5729 | 5841 | /* Copy the entity tables. */ |
| 5730 | | if (!copyEntityTable(&(newDtd->generalEntities), |
| 5842 | if (!copyEntityTable(oldParser, |
| 5843 | &(newDtd->generalEntities), |
| 5731 | 5844 | &(newDtd->pool), |
| 5732 | 5845 | &(oldDtd->generalEntities))) |
| 5733 | 5846 | return 0; |
| 5734 | 5847 | |
| 5735 | 5848 | #ifdef XML_DTD |
| 5736 | | if (!copyEntityTable(&(newDtd->paramEntities), |
| 5849 | if (!copyEntityTable(oldParser, |
| 5850 | &(newDtd->paramEntities), |
| 5737 | 5851 | &(newDtd->pool), |
| 5738 | 5852 | &(oldDtd->paramEntities))) |
| 5739 | 5853 | return 0; |
| r15669 | r15670 | |
| 5756 | 5870 | } /* End dtdCopy */ |
| 5757 | 5871 | |
| 5758 | 5872 | static int |
| 5759 | | copyEntityTable(HASH_TABLE *newTable, |
| 5873 | copyEntityTable(XML_Parser oldParser, |
| 5874 | HASH_TABLE *newTable, |
| 5760 | 5875 | STRING_POOL *newPool, |
| 5761 | 5876 | const HASH_TABLE *oldTable) |
| 5762 | 5877 | { |
| r15669 | r15670 | |
| 5775 | 5890 | name = poolCopyString(newPool, oldE->name); |
| 5776 | 5891 | if (!name) |
| 5777 | 5892 | return 0; |
| 5778 | | newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY)); |
| 5893 | newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY)); |
| 5779 | 5894 | if (!newE) |
| 5780 | 5895 | return 0; |
| 5781 | 5896 | if (oldE->systemId) { |
| r15669 | r15670 | |
| 5833 | 5948 | } |
| 5834 | 5949 | |
| 5835 | 5950 | static unsigned long FASTCALL |
| 5836 | | hash(KEY s) |
| 5951 | hash(XML_Parser parser, KEY s) |
| 5837 | 5952 | { |
| 5838 | | unsigned long h = 0; |
| 5953 | unsigned long h = hash_secret_salt; |
| 5839 | 5954 | while (*s) |
| 5840 | 5955 | h = CHAR_HASH(h, *s++); |
| 5841 | 5956 | return h; |
| 5842 | 5957 | } |
| 5843 | 5958 | |
| 5844 | 5959 | static NAMED * |
| 5845 | | lookup(HASH_TABLE *table, KEY name, size_t createSize) |
| 5960 | lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) |
| 5846 | 5961 | { |
| 5847 | 5962 | size_t i; |
| 5848 | 5963 | if (table->size == 0) { |
| r15669 | r15670 | |
| 5859 | 5974 | return NULL; |
| 5860 | 5975 | } |
| 5861 | 5976 | memset(table->v, 0, tsize); |
| 5862 | | i = hash(name) & ((unsigned long)table->size - 1); |
| 5977 | i = hash(parser, name) & ((unsigned long)table->size - 1); |
| 5863 | 5978 | } |
| 5864 | 5979 | else { |
| 5865 | | unsigned long h = hash(name); |
| 5980 | unsigned long h = hash(parser, name); |
| 5866 | 5981 | unsigned long mask = (unsigned long)table->size - 1; |
| 5867 | 5982 | unsigned char step = 0; |
| 5868 | 5983 | i = h & mask; |
| r15669 | r15670 | |
| 5888 | 6003 | memset(newV, 0, tsize); |
| 5889 | 6004 | for (i = 0; i < table->size; i++) |
| 5890 | 6005 | if (table->v[i]) { |
| 5891 | | unsigned long newHash = hash(table->v[i]->name); |
| 6006 | unsigned long newHash = hash(parser, table->v[i]->name); |
| 5892 | 6007 | size_t j = newHash & newMask; |
| 5893 | 6008 | step = 0; |
| 5894 | 6009 | while (newV[j]) { |
| r15669 | r15670 | |
| 6109 | 6224 | } |
| 6110 | 6225 | if (pool->blocks && pool->start == pool->blocks->s) { |
| 6111 | 6226 | int blockSize = (int)(pool->end - pool->start)*2; |
| 6112 | | pool->blocks = (BLOCK *) |
| 6227 | BLOCK *temp = (BLOCK *) |
| 6113 | 6228 | pool->mem->realloc_fcn(pool->blocks, |
| 6114 | 6229 | (offsetof(BLOCK, s) |
| 6115 | 6230 | + blockSize * sizeof(XML_Char))); |
| 6116 | | if (pool->blocks == NULL) |
| 6231 | if (temp == NULL) |
| 6117 | 6232 | return XML_FALSE; |
| 6233 | pool->blocks = temp; |
| 6118 | 6234 | pool->blocks->size = blockSize; |
| 6119 | 6235 | pool->ptr = pool->blocks->s + (pool->ptr - pool->start); |
| 6120 | 6236 | pool->start = pool->blocks->s; |
| r15669 | r15670 | |
| 6263 | 6379 | |
| 6264 | 6380 | if (!name) |
| 6265 | 6381 | return NULL; |
| 6266 | | ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); |
| 6382 | ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); |
| 6267 | 6383 | if (!ret) |
| 6268 | 6384 | return NULL; |
| 6269 | 6385 | if (ret->name != name) |