diff options
author | Mike Hommey <glandium@debian.org> | 2006-04-29 21:57:40 +0200 |
---|---|---|
committer | Mike Hommey <glandium@debian.org> | 2006-04-29 21:57:40 +0200 |
commit | 07a67fa4bcc1b8bf2651ab41e5fc54a05059cf7e (patch) | |
tree | 7b377fd8e804a983cb2c57a43be1093ef179c5fd /xmlregexp.c | |
parent | c5d565931c4823dc8f62fffcb65aecfec516f7b9 (diff) | |
download | libxml2-07a67fa4bcc1b8bf2651ab41e5fc54a05059cf7e.tar.gz |
Load /tmp/libxml2-2.6.24 intoupstream/2.6.24.dfsg
libxml2/branches/upstream/current.
Diffstat (limited to 'xmlregexp.c')
-rw-r--r-- | xmlregexp.c | 390 |
1 files changed, 341 insertions, 49 deletions
diff --git a/xmlregexp.c b/xmlregexp.c index de581f0..58f480d 100644 --- a/xmlregexp.c +++ b/xmlregexp.c @@ -71,6 +71,9 @@ * * ************************************************************************/ +/* + * Note: the order of the enums below is significant, do not shuffle + */ typedef enum { XML_REGEXP_EPSILON = 1, XML_REGEXP_CHARVAL, @@ -1476,7 +1479,13 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from, switch (atom->quant) { case XML_REGEXP_QUANT_OPT: atom->quant = XML_REGEXP_QUANT_ONCE; - xmlFAGenerateEpsilonTransition(ctxt, atom->start, atom->stop); + /* + * transition done to the state after end of atom. + * 1. set transition from atom start to new state + * 2. set transition from atom end to this state. + */ + xmlFAGenerateEpsilonTransition(ctxt, atom->start, 0); + xmlFAGenerateEpsilonTransition(ctxt, atom->stop, ctxt->state); break; case XML_REGEXP_QUANT_MULT: atom->quant = XML_REGEXP_QUANT_ONCE; @@ -1519,8 +1528,6 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from, atom->min = 0; atom->max = 0; atom->quant = XML_REGEXP_QUANT_ONCE; - xmlFAGenerateCountedEpsilonTransition(ctxt, atom->stop, - atom->start, counter); if (to != NULL) { newstate = to; } else { @@ -1530,6 +1537,13 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from, ctxt->state = newstate; xmlFAGenerateCountedTransition(ctxt, atom->stop, newstate, counter); + + /* + * first check count and if OK jump forward; + * if checking fail increment count and jump back + */ + xmlFAGenerateCountedEpsilonTransition(ctxt, atom->stop, + atom->start, counter); } default: break; @@ -2054,34 +2068,281 @@ xmlFACompareRanges(xmlRegRangePtr range1, xmlRegRangePtr range2) { } /** + * xmlFACompareAtomTypes: + * @type1: an atom type + * @type2: an atom type + * + * Compares two atoms type to check whether they intersect in some ways, + * this is used by xmlFACompareAtoms only + * + * Returns 1 if they may intersect and 0 otherwise + */ +static int +xmlFACompareAtomTypes(xmlRegAtomType type1, xmlRegAtomType type2) { + if ((type1 == XML_REGEXP_EPSILON) || + (type1 == XML_REGEXP_CHARVAL) || + (type1 == XML_REGEXP_RANGES) || + (type1 == XML_REGEXP_SUBREG) || + (type1 == XML_REGEXP_STRING) || + (type1 == XML_REGEXP_ANYCHAR)) + return(1); + if ((type2 == XML_REGEXP_EPSILON) || + (type2 == XML_REGEXP_CHARVAL) || + (type2 == XML_REGEXP_RANGES) || + (type2 == XML_REGEXP_SUBREG) || + (type2 == XML_REGEXP_STRING) || + (type2 == XML_REGEXP_ANYCHAR)) + return(1); + + if (type1 == type2) return(1); + + /* simplify subsequent compares by making sure type1 < type2 */ + if (type1 > type2) { + xmlRegAtomType tmp = type1; + type1 = type2; + type2 = tmp; + } + switch (type1) { + case XML_REGEXP_ANYSPACE: /* \s */ + /* can't be a letter, number, mark, pontuation, symbol */ + if ((type2 == XML_REGEXP_NOTSPACE) || + ((type2 >= XML_REGEXP_LETTER) && + (type2 <= XML_REGEXP_LETTER_OTHERS)) || + ((type2 >= XML_REGEXP_NUMBER) && + (type2 <= XML_REGEXP_NUMBER_OTHERS)) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) + ) return(0); + break; + case XML_REGEXP_NOTSPACE: /* \S */ + break; + case XML_REGEXP_INITNAME: /* \l */ + /* can't be a number, mark, separator, pontuation, symbol or other */ + if ((type2 == XML_REGEXP_NOTINITNAME) || + ((type2 >= XML_REGEXP_NUMBER) && + (type2 <= XML_REGEXP_NUMBER_OTHERS)) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_SEPAR) && + (type2 <= XML_REGEXP_SEPAR_PARA)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) || + ((type2 >= XML_REGEXP_OTHER) && + (type2 <= XML_REGEXP_OTHER_NA)) + ) return(0); + break; + case XML_REGEXP_NOTINITNAME: /* \L */ + break; + case XML_REGEXP_NAMECHAR: /* \c */ + /* can't be a mark, separator, pontuation, symbol or other */ + if ((type2 == XML_REGEXP_NOTNAMECHAR) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SEPAR) && + (type2 <= XML_REGEXP_SEPAR_PARA)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) || + ((type2 >= XML_REGEXP_OTHER) && + (type2 <= XML_REGEXP_OTHER_NA)) + ) return(0); + break; + case XML_REGEXP_NOTNAMECHAR: /* \C */ + break; + case XML_REGEXP_DECIMAL: /* \d */ + /* can't be a letter, mark, separator, pontuation, symbol or other */ + if ((type2 == XML_REGEXP_NOTDECIMAL) || + (type2 == XML_REGEXP_REALCHAR) || + ((type2 >= XML_REGEXP_LETTER) && + (type2 <= XML_REGEXP_LETTER_OTHERS)) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SEPAR) && + (type2 <= XML_REGEXP_SEPAR_PARA)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) || + ((type2 >= XML_REGEXP_OTHER) && + (type2 <= XML_REGEXP_OTHER_NA)) + )return(0); + break; + case XML_REGEXP_NOTDECIMAL: /* \D */ + break; + case XML_REGEXP_REALCHAR: /* \w */ + /* can't be a mark, separator, pontuation, symbol or other */ + if ((type2 == XML_REGEXP_NOTDECIMAL) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SEPAR) && + (type2 <= XML_REGEXP_SEPAR_PARA)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) || + ((type2 >= XML_REGEXP_OTHER) && + (type2 <= XML_REGEXP_OTHER_NA)) + )return(0); + break; + case XML_REGEXP_NOTREALCHAR: /* \W */ + break; + /* + * at that point we know both type 1 and type2 are from + * character categories are ordered and are different, + * it becomes simple because this is a partition + */ + case XML_REGEXP_LETTER: + if (type2 <= XML_REGEXP_LETTER_OTHERS) + return(1); + return(0); + case XML_REGEXP_LETTER_UPPERCASE: + case XML_REGEXP_LETTER_LOWERCASE: + case XML_REGEXP_LETTER_TITLECASE: + case XML_REGEXP_LETTER_MODIFIER: + case XML_REGEXP_LETTER_OTHERS: + return(0); + case XML_REGEXP_MARK: + if (type2 <= XML_REGEXP_MARK_ENCLOSING) + return(1); + return(0); + case XML_REGEXP_MARK_NONSPACING: + case XML_REGEXP_MARK_SPACECOMBINING: + case XML_REGEXP_MARK_ENCLOSING: + return(0); + case XML_REGEXP_NUMBER: + if (type2 <= XML_REGEXP_NUMBER_OTHERS) + return(1); + return(0); + case XML_REGEXP_NUMBER_DECIMAL: + case XML_REGEXP_NUMBER_LETTER: + case XML_REGEXP_NUMBER_OTHERS: + return(0); + case XML_REGEXP_PUNCT: + if (type2 <= XML_REGEXP_PUNCT_OTHERS) + return(1); + return(0); + case XML_REGEXP_PUNCT_CONNECTOR: + case XML_REGEXP_PUNCT_DASH: + case XML_REGEXP_PUNCT_OPEN: + case XML_REGEXP_PUNCT_CLOSE: + case XML_REGEXP_PUNCT_INITQUOTE: + case XML_REGEXP_PUNCT_FINQUOTE: + case XML_REGEXP_PUNCT_OTHERS: + return(0); + case XML_REGEXP_SEPAR: + if (type2 <= XML_REGEXP_SEPAR_PARA) + return(1); + return(0); + case XML_REGEXP_SEPAR_SPACE: + case XML_REGEXP_SEPAR_LINE: + case XML_REGEXP_SEPAR_PARA: + return(0); + case XML_REGEXP_SYMBOL: + if (type2 <= XML_REGEXP_SYMBOL_OTHERS) + return(1); + return(0); + case XML_REGEXP_SYMBOL_MATH: + case XML_REGEXP_SYMBOL_CURRENCY: + case XML_REGEXP_SYMBOL_MODIFIER: + case XML_REGEXP_SYMBOL_OTHERS: + return(0); + case XML_REGEXP_OTHER: + if (type2 <= XML_REGEXP_OTHER_NA) + return(1); + return(0); + case XML_REGEXP_OTHER_CONTROL: + case XML_REGEXP_OTHER_FORMAT: + case XML_REGEXP_OTHER_PRIVATE: + case XML_REGEXP_OTHER_NA: + return(0); + default: + break; + } + return(1); +} + +/** + * xmlFAEqualAtoms: + * @atom1: an atom + * @atom2: an atom + * + * Compares two atoms to check whether they are the same exactly + * this is used to remove equivalent transitions + * + * Returns 1 if same and 0 otherwise + */ +static int +xmlFAEqualAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2) { + int ret = 0; + + if (atom1 == atom2) + return(1); + if ((atom1 == NULL) || (atom2 == NULL)) + return(0); + + if (atom1->type != atom2->type) + return(0); + switch (atom1->type) { + case XML_REGEXP_EPSILON: + ret = 0; + break; + case XML_REGEXP_STRING: + ret = xmlStrEqual((xmlChar *)atom1->valuep, + (xmlChar *)atom2->valuep); + break; + case XML_REGEXP_CHARVAL: + ret = (atom1->codepoint == atom2->codepoint); + break; + case XML_REGEXP_RANGES: + /* too hard to do in the general case */ + ret = 0; + default: + break; + } + return(ret); +} + +/** * xmlFACompareAtoms: * @atom1: an atom * @atom2: an atom * * Compares two atoms to check whether they intersect in some ways, - * this is used by xmlFAComputesDeterminism only + * this is used by xmlFAComputesDeterminism and xmlFARecurseDeterminism only * * Returns 1 if yes and 0 otherwise */ static int xmlFACompareAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2) { - int ret; + int ret = 1; if (atom1 == atom2) return(1); if ((atom1 == NULL) || (atom2 == NULL)) return(0); - if ((atom1->type == XML_REGEXP_RANGES) && - (atom2->type == XML_REGEXP_CHARVAL)) { - } else if ((atom1->type == XML_REGEXP_CHARVAL) && - (atom2->type == XML_REGEXP_RANGES)) { + if ((atom1->type == XML_REGEXP_ANYCHAR) || + (atom2->type == XML_REGEXP_ANYCHAR)) + return(1); + + if (atom1->type > atom2->type) { xmlRegAtomPtr tmp; tmp = atom1; atom1 = atom2; atom2 = tmp; - } else if (atom1->type != atom2->type) { - return(0); + } + if (atom1->type != atom2->type) { + ret = xmlFACompareAtomTypes(atom1->type, atom2->type); + /* if they can't intersect at the type level break now */ + if (ret == 0) + return(0); } switch (atom1->type) { case XML_REGEXP_STRING: @@ -2091,15 +2352,16 @@ xmlFACompareAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2) { case XML_REGEXP_EPSILON: goto not_determinist; case XML_REGEXP_CHARVAL: - ret = (atom1->codepoint == atom2->codepoint); - break; - case XML_REGEXP_RANGES: if (atom2->type == XML_REGEXP_CHARVAL) { - ret = xmlRegCheckCharacter(atom1, atom2->codepoint); - if (ret < 0) - return(-1); - break; + ret = (atom1->codepoint == atom2->codepoint); } else { + ret = xmlRegCheckCharacter(atom2, atom1->codepoint); + if (ret < 0) + ret = 1; + } + break; + case XML_REGEXP_RANGES: + if (atom2->type == XML_REGEXP_RANGES) { int i, j, res; xmlRegRangePtr r1, r2; @@ -2233,7 +2495,7 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) { continue; if (t2->atom != NULL) { if (t1->to == t2->to) { - if (xmlFACompareAtoms(t1->atom, t2->atom)) + if (xmlFAEqualAtoms(t1->atom, t2->atom)) t2->to = -1; /* eliminated */ } } @@ -2759,6 +3021,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { * if we are working on a range like "AB{0,2}", where B is not present, * we don't want to break. */ + len = 1; if ((exec->inputString[exec->index] == 0) && (exec->counts == NULL)) { /* * if there is a transition, we must check if @@ -2787,6 +3050,10 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { int count; xmlRegCounterPtr counter; + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } /* * A counted transition. */ @@ -2816,6 +3083,10 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { * before potentially saving and rollback */ if (trans->counter >= 0) { + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } #ifdef DEBUG_REGEXP_EXEC printf("Increasing count %d\n", trans->counter); #endif @@ -2871,6 +3142,10 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { goto rollback; } if (trans->counter >= 0) { + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } #ifdef DEBUG_REGEXP_EXEC printf("Decreasing count %d\n", trans->counter); #endif @@ -2907,6 +3182,10 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { xmlFARegExecSave(exec); } if (trans->counter >= 0) { + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } #ifdef DEBUG_REGEXP_EXEC printf("Increasing count %d\n", trans->counter); #endif @@ -2914,6 +3193,10 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { } if ((trans->count >= 0) && (trans->count < REGEXP_ALL_COUNTER)) { + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } #ifdef DEBUG_REGEXP_EXEC printf("resetting count %d on transition\n", trans->count); @@ -2949,6 +3232,7 @@ rollback: progress: continue; } +error: if (exec->rollbacks != NULL) { if (exec->counts != NULL) { int i; @@ -3355,6 +3639,7 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, } if ((count >= counter->min) && (count < counter->max) && + (t->atom != NULL) && (xmlStrEqual(value, t->atom->valuep))) { ret = 1; break; @@ -3784,15 +4069,16 @@ xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err, /* this should not be reached but ... */ TODO; } else if (trans->counter >= 0) { - xmlRegCounterPtr counter; + xmlRegCounterPtr counter = NULL; int count; if (err) count = exec->errCounts[trans->counter]; else count = exec->counts[trans->counter]; - counter = &exec->comp->counters[trans->counter]; - if (count < counter->max) { + if (exec->comp != NULL) + counter = &exec->comp->counters[trans->counter]; + if ((counter == NULL) || (count < counter->max)) { if (atom->neg) values[nb++] = (xmlChar *) atom->valuep2; else @@ -4024,6 +4310,15 @@ xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) { if (exec->state->nbTrans > exec->transno + 1) { xmlFARegExecSave(exec); } + /* + * restart count for expressions like this ((abc){2})* + */ + if (trans->count >= 0) { +#ifdef DEBUG_REGEXP_EXEC + printf("Reset count %d\n", trans->count); +#endif + exec->counts[trans->count] = 0; + } if (trans->counter >= 0) { #ifdef DEBUG_REGEXP_EXEC printf("Increasing count %d\n", trans->counter); @@ -4460,6 +4755,7 @@ xmlFAParseCharRef(xmlRegParserCtxtPtr ctxt) { ((cur >= 'a') && (cur <= 'f')) || ((cur >= 'A') && (cur <= 'F'))) { while (((cur >= '0') && (cur <= '9')) || + ((cur >= 'a') && (cur <= 'f')) || ((cur >= 'A') && (cur <= 'F'))) { if ((cur >= '0') && (cur <= '9')) ret = ret * 16 + cur - '0'; @@ -4836,19 +5132,23 @@ xmlFAParsePiece(xmlRegParserCtxtPtr ctxt) { /** * xmlFAParseBranch: * @ctxt: a regexp parser context + * @to: optional target to the end of the branch + * + * @to is used to optimize by removing duplicate path in automata + * in expressions like (a|b)(c|d) * * [2] branch ::= piece* - 8 */ static int -xmlFAParseBranch(xmlRegParserCtxtPtr ctxt) { +xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr to) { xmlRegStatePtr previous; int ret; previous = ctxt->state; ret = xmlFAParsePiece(ctxt); if (ret != 0) { - if (xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom) < 0) + if (xmlFAGenerateTransitions(ctxt, previous, + (CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0) return(-1); previous = ctxt->state; ctxt->atom = NULL; @@ -4856,8 +5156,8 @@ xmlFAParseBranch(xmlRegParserCtxtPtr ctxt) { while ((ret != 0) && (ctxt->error == 0)) { ret = xmlFAParsePiece(ctxt); if (ret != 0) { - if (xmlFAGenerateTransitions(ctxt, previous, NULL, - ctxt->atom) < 0) + if (xmlFAGenerateTransitions(ctxt, previous, + (CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0) return(-1); previous = ctxt->state; ctxt->atom = NULL; @@ -4880,7 +5180,7 @@ xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) { /* if not top start should have been generated by an epsilon trans */ start = ctxt->state; ctxt->end = NULL; - xmlFAParseBranch(ctxt); + xmlFAParseBranch(ctxt, NULL); if (top) { #ifdef DEBUG_REGEXP_GRAPH printf("State %d is final\n", ctxt->state->no); @@ -4896,15 +5196,7 @@ xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) { NEXT; ctxt->state = start; ctxt->end = NULL; - xmlFAParseBranch(ctxt); - if (top) { - ctxt->state->type = XML_REGEXP_FINAL_STATE; -#ifdef DEBUG_REGEXP_GRAPH - printf("State %d is final\n", ctxt->state->no); -#endif - } else { - xmlFAGenerateEpsilonTransition(ctxt, ctxt->state, end); - } + xmlFAParseBranch(ctxt, end); } if (!top) { ctxt->state = end; @@ -5241,9 +5533,9 @@ xmlAutomataNewTransition2(xmlAutomataPtr am, xmlAutomataStatePtr from, if ((am == NULL) || (from == NULL) || (token == NULL)) return(NULL); atom = xmlRegNewAtom(am, XML_REGEXP_STRING); - atom->data = data; if (atom == NULL) return(NULL); + atom->data = data; if ((token2 == NULL) || (*token2 == 0)) { atom->valuep = xmlStrdup(token); } else { @@ -5554,10 +5846,7 @@ xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from, } atom->data = data; atom->quant = XML_REGEXP_QUANT_ONCEONLY; - if (min == 0) - atom->min = 1; - else - atom->min = min; + atom->min = min; atom->max = max; /* * associate a counter to the transition. @@ -5616,10 +5905,7 @@ xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from, atom->valuep = xmlStrdup(token); atom->data = data; atom->quant = XML_REGEXP_QUANT_ONCEONLY; - if (min == 0) - atom->min = 1; - else - atom->min = min; + atom->min = min; atom->max = max; /* * associate a counter to the transition. @@ -6370,7 +6656,9 @@ xmlExpNewAtom(xmlExpCtxtPtr ctxt, const xmlChar *name, int len) { */ xmlExpNodePtr xmlExpNewOr(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) { - if ((ctxt == NULL) || (left == NULL) || (right == NULL)) { + if (ctxt == NULL) + return(NULL); + if ((left == NULL) || (right == NULL)) { xmlExpFree(ctxt, left); xmlExpFree(ctxt, right); return(NULL); @@ -6393,7 +6681,9 @@ xmlExpNewOr(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) { */ xmlExpNodePtr xmlExpNewSeq(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) { - if ((ctxt == NULL) || (left == NULL) || (right == NULL)) { + if (ctxt == NULL) + return(NULL); + if ((left == NULL) || (right == NULL)) { xmlExpFree(ctxt, left); xmlExpFree(ctxt, right); return(NULL); @@ -6417,7 +6707,9 @@ xmlExpNewSeq(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) { */ xmlExpNodePtr xmlExpNewRange(xmlExpCtxtPtr ctxt, xmlExpNodePtr subset, int min, int max) { - if ((ctxt == NULL) || (subset == NULL) || (min < 0) || (max < -1) || + if (ctxt == NULL) + return(NULL); + if ((subset == NULL) || (min < 0) || (max < -1) || ((max >= 0) && (min > max))) { xmlExpFree(ctxt, subset); return(NULL); |