Commit 6ed2eb47 authored by Kasimier T. Buchcik's avatar Kasimier T. Buchcik
Browse files

Applied patch from Rob Richards, fixing a potential memory leak in

* xpath.c: Applied patch from Rob Richards, fixing a potential
  memory leak in xmlXPathTryStreamCompile(), when a list of
  namespaces was assigned to the XPath compilation context;
  here a new namespace list was created and passed to
  xmlPatterncompile(); but this list was not freed afterwards.
  Additionally we avoid now in xmlXPathTryStreamCompile() to
  compile the expression, if it has a colon - indicating
  prefixed name tests - and no namespace list was given. The
  streaming XPath mechanism needs a namespace list at
  compilation time (unlike normal XPath, where we can bind
  namespace names to prefixes at execution time).
* pattern.c: Enhanced to use a string dict for local-names,
  ns-prefixes and and namespace-names.
  Fixed xmlStreamPushInternal() not to use string-pointer
  comparison if a dict is available; this won't work, since
  one does not know it the given strings originate from the
  same dict - and they normally don't do, since e.g.
  namespaces are hold on xmlNs->href. I think this would be
  worth an investigation: if we can add a @doc field to xmlNs
  and put the @href in to a additionan namespace dict hold
  in xmlDoc. Daniel will surely not like this idea :-) But
  evaluation of tons of elements/attributes in namespaces
  with xmlStrEqual() isn't the way we should go forever.
parent 9b02e295
Tue May 16 16:55:13 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
* xpath.c: Applied patch from Rob Richards, fixing a potential
memory leak in xmlXPathTryStreamCompile(), when a list of
namespaces was assigned to the XPath compilation context;
here a new namespace list was created and passed to
xmlPatterncompile(); but this list was not freed afterwards.
Additionally we avoid now in xmlXPathTryStreamCompile() to
compile the expression, if it has a colon - indicating
prefixed name tests - and no namespace list was given. The
streaming XPath mechanism needs a namespace list at
compilation time (unlike normal XPath, where we can bind
namespace names to prefixes at execution time).
* pattern.c: Enhanced to use a string dict for local-names,
ns-prefixes and and namespace-names.
Fixed xmlStreamPushInternal() not to use string-pointer
comparison if a dict is available; this won't work, since
one does not know it the given strings originate from the
same dict - and they normally don't do, since e.g.
namespaces are hold on xmlNs->href. I think this would be
worth an investigation: if we can add a @doc field to xmlNs
and put the @href in to a additionan namespace dict hold
in xmlDoc. Daniel will surely not like this idea :-) But
evaluation of tons of elements/attributes in namespaces
with xmlStrEqual() isn't the way we should go forever.
Thu May 11 18:03:49 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net> Thu May 11 18:03:49 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
   
* xmlschemas.c: Fixed bug #341337, reported by David Grohmann. * xmlschemas.c: Fixed bug #341337, reported by David Grohmann.
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
* and indicating we are on / (the document node), probably need * and indicating we are on / (the document node), probably need
* something similar for . * something similar for .
* - get rid of the "compile" starting with lowercase * - get rid of the "compile" starting with lowercase
* - get rid of the Strdup/Strndup in case of dictionary * - DONE (2006-05-16): get rid of the Strdup/Strndup in case of dictionary
*/ */
#define IN_LIBXML #define IN_LIBXML
...@@ -76,6 +76,13 @@ ...@@ -76,6 +76,13 @@
#define XML_STREAM_XS_IDC_FIELD(c) ((c)->flags & XML_PATTERN_XSFIELD) #define XML_STREAM_XS_IDC_FIELD(c) ((c)->flags & XML_PATTERN_XSFIELD)
#define XML_PAT_COPY_NSNAME(c, r, nsname) \
if ((c)->comp->dict) \
r = (xmlChar *) xmlDictLookup((c)->comp->dict, BAD_CAST nsname, -1); \
else r = xmlStrdup(BAD_CAST nsname);
#define XML_PAT_FREE_STRING(c, r) if ((c)->comp->dict == NULL) xmlFree(r);
typedef struct _xmlStreamStep xmlStreamStep; typedef struct _xmlStreamStep xmlStreamStep;
typedef xmlStreamStep *xmlStreamStepPtr; typedef xmlStreamStep *xmlStreamStepPtr;
struct _xmlStreamStep { struct _xmlStreamStep {
...@@ -145,7 +152,7 @@ typedef xmlStepOp *xmlStepOpPtr; ...@@ -145,7 +152,7 @@ typedef xmlStepOp *xmlStepOpPtr;
struct _xmlStepOp { struct _xmlStepOp {
xmlPatOp op; xmlPatOp op;
const xmlChar *value; const xmlChar *value;
const xmlChar *value2; const xmlChar *value2; /* The namespace name */
}; };
#define PAT_FROM_ROOT (1<<8) #define PAT_FROM_ROOT (1<<8)
...@@ -758,6 +765,9 @@ xmlPatScanLiteral(xmlPatParserContextPtr ctxt) { ...@@ -758,6 +765,9 @@ xmlPatScanLiteral(xmlPatParserContextPtr ctxt) {
ctxt->error = 1; ctxt->error = 1;
return(NULL); return(NULL);
} else { } else {
if (ctxt->dict)
ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
else
ret = xmlStrndup(q, cur - q); ret = xmlStrndup(q, cur - q);
} }
cur += len; cur += len;
...@@ -774,6 +784,9 @@ xmlPatScanLiteral(xmlPatParserContextPtr ctxt) { ...@@ -774,6 +784,9 @@ xmlPatScanLiteral(xmlPatParserContextPtr ctxt) {
ctxt->error = 1; ctxt->error = 1;
return(NULL); return(NULL);
} else { } else {
if (ctxt->dict)
ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
else
ret = xmlStrndup(q, cur - q); ret = xmlStrndup(q, cur - q);
} }
cur += len; cur += len;
...@@ -822,6 +835,9 @@ xmlPatScanName(xmlPatParserContextPtr ctxt) { ...@@ -822,6 +835,9 @@ xmlPatScanName(xmlPatParserContextPtr ctxt) {
cur += len; cur += len;
val = xmlStringCurrentChar(NULL, cur, &len); val = xmlStringCurrentChar(NULL, cur, &len);
} }
if (ctxt->dict)
ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
else
ret = xmlStrndup(q, cur - q); ret = xmlStrndup(q, cur - q);
CUR_PTR = cur; CUR_PTR = cur;
return(ret); return(ret);
...@@ -857,6 +873,9 @@ xmlPatScanNCName(xmlPatParserContextPtr ctxt) { ...@@ -857,6 +873,9 @@ xmlPatScanNCName(xmlPatParserContextPtr ctxt) {
cur += len; cur += len;
val = xmlStringCurrentChar(NULL, cur, &len); val = xmlStringCurrentChar(NULL, cur, &len);
} }
if (ctxt->dict)
ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
else
ret = xmlStrndup(q, cur - q); ret = xmlStrndup(q, cur - q);
CUR_PTR = cur; CUR_PTR = cur;
return(ret); return(ret);
...@@ -921,7 +940,7 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { ...@@ -921,7 +940,7 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
if (IS_BLANK_CH(CUR)) { if (IS_BLANK_CH(CUR)) {
ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
xmlFree(prefix); XML_PAT_FREE_STRING(ctxt, prefix);
ctxt->error = 1; ctxt->error = 1;
goto error; goto error;
} }
...@@ -932,12 +951,13 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { ...@@ -932,12 +951,13 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
if ((prefix[0] == 'x') && if ((prefix[0] == 'x') &&
(prefix[1] == 'm') && (prefix[1] == 'm') &&
(prefix[2] == 'l') && (prefix[2] == 'l') &&
(prefix[3] == 0)) { (prefix[3] == 0))
URL = xmlStrdup(XML_XML_NAMESPACE); {
XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE);
} else { } else {
for (i = 0;i < ctxt->nb_namespaces;i++) { for (i = 0;i < ctxt->nb_namespaces;i++) {
if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) { if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
URL = xmlStrdup(ctxt->namespaces[2 * i]); XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
break; break;
} }
} }
...@@ -949,7 +969,7 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { ...@@ -949,7 +969,7 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
goto error; goto error;
} }
} }
xmlFree(prefix); XML_PAT_FREE_STRING(ctxt, prefix);
if (token == NULL) { if (token == NULL) {
if (CUR == '*') { if (CUR == '*') {
NEXT; NEXT;
...@@ -969,12 +989,11 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { ...@@ -969,12 +989,11 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
return; return;
error: error:
if (URL != NULL) if (URL != NULL)
xmlFree(URL); XML_PAT_FREE_STRING(ctxt, URL)
if (token != NULL) if (token != NULL)
xmlFree(token); XML_PAT_FREE_STRING(ctxt, token);
} }
/** /**
* xmlCompileStepPattern: * xmlCompileStepPattern:
* @ctxt: the compilation context * @ctxt: the compilation context
...@@ -1053,12 +1072,13 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { ...@@ -1053,12 +1072,13 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
if ((prefix[0] == 'x') && if ((prefix[0] == 'x') &&
(prefix[1] == 'm') && (prefix[1] == 'm') &&
(prefix[2] == 'l') && (prefix[2] == 'l') &&
(prefix[3] == 0)) { (prefix[3] == 0))
URL = xmlStrdup(XML_XML_NAMESPACE); {
XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
} else { } else {
for (i = 0;i < ctxt->nb_namespaces;i++) { for (i = 0;i < ctxt->nb_namespaces;i++) {
if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) { if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
URL = xmlStrdup(ctxt->namespaces[2 * i]); XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
break; break;
} }
} }
...@@ -1070,7 +1090,7 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { ...@@ -1070,7 +1090,7 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
goto error; goto error;
} }
} }
xmlFree(prefix); XML_PAT_FREE_STRING(ctxt, prefix);
if (token == NULL) { if (token == NULL) {
if (CUR == '*') { if (CUR == '*') {
NEXT; NEXT;
...@@ -1087,7 +1107,7 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { ...@@ -1087,7 +1107,7 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
} else { } else {
NEXT; NEXT;
if (xmlStrEqual(name, (const xmlChar *) "child")) { if (xmlStrEqual(name, (const xmlChar *) "child")) {
xmlFree(name); XML_PAT_FREE_STRING(ctxt, name);
name = xmlPatScanName(ctxt); name = xmlPatScanName(ctxt);
if (name == NULL) { if (name == NULL) {
if (CUR == '*') { if (CUR == '*') {
...@@ -1118,12 +1138,13 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { ...@@ -1118,12 +1138,13 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
if ((prefix[0] == 'x') && if ((prefix[0] == 'x') &&
(prefix[1] == 'm') && (prefix[1] == 'm') &&
(prefix[2] == 'l') && (prefix[2] == 'l') &&
(prefix[3] == 0)) { (prefix[3] == 0))
URL = xmlStrdup(XML_XML_NAMESPACE); {
XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
} else { } else {
for (i = 0;i < ctxt->nb_namespaces;i++) { for (i = 0;i < ctxt->nb_namespaces;i++) {
if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) { if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
URL = xmlStrdup(ctxt->namespaces[2 * i]); XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
break; break;
} }
} }
...@@ -1135,7 +1156,7 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { ...@@ -1135,7 +1156,7 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
goto error; goto error;
} }
} }
xmlFree(prefix); XML_PAT_FREE_STRING(ctxt, prefix);
if (token == NULL) { if (token == NULL) {
if (CUR == '*') { if (CUR == '*') {
NEXT; NEXT;
...@@ -1153,7 +1174,7 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { ...@@ -1153,7 +1174,7 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
PUSH(XML_OP_CHILD, name, NULL); PUSH(XML_OP_CHILD, name, NULL);
return; return;
} else if (xmlStrEqual(name, (const xmlChar *) "attribute")) { } else if (xmlStrEqual(name, (const xmlChar *) "attribute")) {
xmlFree(name); XML_PAT_FREE_STRING(ctxt, name)
name = NULL; name = NULL;
if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) { if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) {
ERROR5(NULL, NULL, NULL, ERROR5(NULL, NULL, NULL,
...@@ -1171,7 +1192,6 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { ...@@ -1171,7 +1192,6 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
ctxt->error = 1; ctxt->error = 1;
goto error; goto error;
} }
/* NOT REACHED xmlFree(name); */
} }
} else if (CUR == '*') { } else if (CUR == '*') {
if (name != NULL) { if (name != NULL) {
...@@ -1186,11 +1206,11 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { ...@@ -1186,11 +1206,11 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
return; return;
error: error:
if (URL != NULL) if (URL != NULL)
xmlFree(URL); XML_PAT_FREE_STRING(ctxt, URL)
if (token != NULL) if (token != NULL)
xmlFree(token); XML_PAT_FREE_STRING(ctxt, token)
if (name != NULL) if (name != NULL)
xmlFree(name); XML_PAT_FREE_STRING(ctxt, name)
} }
/** /**
...@@ -1831,8 +1851,9 @@ static int ...@@ -1831,8 +1851,9 @@ static int
xmlStreamPushInternal(xmlStreamCtxtPtr stream, xmlStreamPushInternal(xmlStreamCtxtPtr stream,
const xmlChar *name, const xmlChar *ns, const xmlChar *name, const xmlChar *ns,
int nodeType) { int nodeType) {
int ret = 0, err = 0, final = 0, tmp, i, m, match, step, desc; int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc;
xmlStreamCompPtr comp; xmlStreamCompPtr comp;
xmlStreamStep step;
#ifdef DEBUG_STREAMING #ifdef DEBUG_STREAMING
xmlStreamCtxtPtr orig = stream; xmlStreamCtxtPtr orig = stream;
#endif #endif
...@@ -1931,7 +1952,7 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, ...@@ -1931,7 +1952,7 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream,
* If there is no "//", then only the last * If there is no "//", then only the last
* added state is of interest. * added state is of interest.
*/ */
step = stream->states[2 * (stream->nbState -1)]; stepNr = stream->states[2 * (stream->nbState -1)];
/* /*
* TODO: Security check, should not happen, remove it. * TODO: Security check, should not happen, remove it.
*/ */
...@@ -1948,10 +1969,10 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, ...@@ -1948,10 +1969,10 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream,
* occuring in the states, plus any other state for this * occuring in the states, plus any other state for this
* level. * level.
*/ */
step = stream->states[2 * i]; stepNr = stream->states[2 * i];
/* TODO: should not happen anymore: dead states */ /* TODO: should not happen anymore: dead states */
if (step < 0) if (stepNr < 0)
goto next_state; goto next_state;
tmp = stream->states[(2 * i) + 1]; tmp = stream->states[(2 * i) + 1];
...@@ -1961,71 +1982,82 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, ...@@ -1961,71 +1982,82 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream,
goto next_state; goto next_state;
/* skip states at ancestor levels, except if "//" */ /* skip states at ancestor levels, except if "//" */
desc = comp->steps[step].flags & XML_STREAM_STEP_DESC; desc = comp->steps[stepNr].flags & XML_STREAM_STEP_DESC;
if ((tmp < stream->level) && (!desc)) if ((tmp < stream->level) && (!desc))
goto next_state; goto next_state;
} }
/* /*
* Check for correct node-type. * Check for correct node-type.
*/ */
if (comp->steps[step].nodeType != nodeType) { step = comp->steps[stepNr];
if (comp->steps[step].nodeType == XML_ATTRIBUTE_NODE) { if (step.nodeType != nodeType) {
if (step.nodeType == XML_ATTRIBUTE_NODE) {
/* /*
* Block this expression for deeper evaluation. * Block this expression for deeper evaluation.
*/ */
if ((comp->flags & XML_STREAM_DESC) == 0) if ((comp->flags & XML_STREAM_DESC) == 0)
stream->blockLevel = stream->level +1; stream->blockLevel = stream->level +1;
goto next_state; goto next_state;
} else if (comp->steps[step].nodeType != XML_STREAM_ANY_NODE) } else if (step.nodeType != XML_STREAM_ANY_NODE)
goto next_state; goto next_state;
} }
/* /*
* Compare local/namespace-name. * Compare local/namespace-name.
*/ */
match = 0; match = 0;
if (comp->steps[step].nodeType == XML_STREAM_ANY_NODE) { if (step.nodeType == XML_STREAM_ANY_NODE) {
match = 1; match = 1;
} else if (comp->dict) { } else if (step.name == NULL) {
if (comp->steps[step].name == NULL) { if (step.ns == NULL) {
if (comp->steps[step].ns == NULL) /*
* This lets through all elements/attributes.
*/
match = 1;
} else if (ns != NULL)
match = xmlStrEqual(step.ns, ns);
} else if (((step.ns != NULL) == (ns != NULL)) &&
(name != NULL) &&
(step.name[0] == name[0]) &&
xmlStrEqual(step.name, name) &&
((step.ns == ns) || xmlStrEqual(step.ns, ns)))
{
match = 1; match = 1;
else
match = (comp->steps[step].ns == ns);
} else {
match = ((comp->steps[step].name == name) &&
(comp->steps[step].ns == ns));
} }
} else { #if 0
if (comp->steps[step].name == NULL) { /*
if (comp->steps[step].ns == NULL) * TODO: Pointer comparison won't work, since not guaranteed that the given
* values are in the same dict; especially if it's the namespace name,
* normally coming from ns->href. We need a namespace dict mechanism !
*/
} else if (comp->dict) {
if (step.name == NULL) {
if (step.ns == NULL)
match = 1; match = 1;
else else
match = xmlStrEqual(comp->steps[step].ns, ns); match = (step.ns == ns);
} else { } else {
match = ((xmlStrEqual(comp->steps[step].name, name)) && match = ((step.name == name) && (step.ns == ns));
(xmlStrEqual(comp->steps[step].ns, ns)));
}
} }
#endif /* if 0 ------------------------------------------------------- */
if (match) { if (match) {
final = comp->steps[step].flags & XML_STREAM_STEP_FINAL; final = step.flags & XML_STREAM_STEP_FINAL;
if (desc) { if (desc) {
if (final) { if (final) {
ret = 1; ret = 1;
} else { } else {
/* descending match create a new state */ /* descending match create a new state */
xmlStreamCtxtAddState(stream, step + 1, xmlStreamCtxtAddState(stream, stepNr + 1,
stream->level + 1); stream->level + 1);
} }
} else { } else {
if (final) { if (final) {
ret = 1; ret = 1;
} else { } else {
xmlStreamCtxtAddState(stream, step + 1, xmlStreamCtxtAddState(stream, stepNr + 1,
stream->level + 1); stream->level + 1);
} }
} }
if ((ret != 1) && if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
(comp->steps[step].flags & XML_STREAM_STEP_IN_SET)) {
/* /*
* Check if we have a special case like "foo/bar//.", where * Check if we have a special case like "foo/bar//.", where
* "foo" is selected as well. * "foo" is selected as well.
...@@ -2053,10 +2085,11 @@ next_state: ...@@ -2053,10 +2085,11 @@ next_state:
* Don't reenter if it's an absolute expression like "/foo", * Don't reenter if it's an absolute expression like "/foo",
* except "//foo". * except "//foo".
*/ */
if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) step = comp->steps[0];
if (step.flags & XML_STREAM_STEP_ROOT)
goto stream_next; goto stream_next;
desc = comp->steps[0].flags & XML_STREAM_STEP_DESC; desc = step.flags & XML_STREAM_STEP_DESC;
if (stream->flags & XML_PATTERN_NOTPATTERN) { if (stream->flags & XML_PATTERN_NOTPATTERN) {
/* /*
* Re/enter the expression if it is a "descendant" one, * Re/enter the expression if it is a "descendant" one,
...@@ -2094,43 +2127,41 @@ compare: ...@@ -2094,43 +2127,41 @@ compare:
/* /*
* Check expected node-type. * Check expected node-type.
*/ */
if (comp->steps[0].nodeType != nodeType) { if (step.nodeType != nodeType) {
if (nodeType == XML_ATTRIBUTE_NODE) if (nodeType == XML_ATTRIBUTE_NODE)
goto stream_next; goto stream_next;
else if (comp->steps[0].nodeType != XML_STREAM_ANY_NODE) else if (step.nodeType != XML_STREAM_ANY_NODE)
goto stream_next; goto stream_next;
} }
/* /*
* Compare local/namespace-name. * Compare local/namespace-name.
*/ */
match = 0; match = 0;
if (comp->steps[0].nodeType == XML_STREAM_ANY_NODE) { if (step.nodeType == XML_STREAM_ANY_NODE) {
match = 1; match = 1;
} else if (comp->steps[0].name == NULL) { } else if (step.name == NULL) {
if (comp->steps[0].ns == NULL) if (step.ns == NULL) {
/*
* This lets through all elements/attributes.
*/
match = 1;
} else if (ns != NULL)
match = xmlStrEqual(step.ns, ns);
} else if (((step.ns != NULL) == (ns != NULL)) &&
(name != NULL) &&
(step.name[0] == name[0]) &&
xmlStrEqual(step.name, name) &&
((step.ns == ns) || xmlStrEqual(step.ns, ns)))
{
match = 1; match = 1;
else {
if (comp->dict)
match = (comp->steps[0].ns == ns);
else
match = xmlStrEqual(comp->steps[0].ns, ns);
}
} else {
if (comp->dict)
match = ((comp->steps[0].name == name) &&
(comp->steps[0].ns == ns));
else
match = ((xmlStrEqual(comp->steps[0].name, name)) &&
(xmlStrEqual(comp->steps[0].ns, ns)));
} }
final = comp->steps[0].flags & XML_STREAM_STEP_FINAL; final = step.flags & XML_STREAM_STEP_FINAL;
if (match) { if (match) {
if (final) if (final)
ret = 1; ret = 1;
else else
xmlStreamCtxtAddState(stream, 1, stream->level); xmlStreamCtxtAddState(stream, 1, stream->level);
if ((ret != 1) && if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
(comp->steps[0].flags & XML_STREAM_STEP_IN_SET)) {
/* /*
* Check if we have a special case like "foo//.", where * Check if we have a special case like "foo//.", where
* "foo" is selected as well. * "foo" is selected as well.
...@@ -2343,6 +2374,13 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags, ...@@ -2343,6 +2374,13 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
if (ctxt == NULL) goto error; if (ctxt == NULL) goto error;
cur = xmlNewPattern