- catalog.c: handling of CATALOG entries. detection of recursion,
and a few bugfixes
- xpath.c: fixing bug #54951 QNAME with no prefix should not match
against the default namespace
Daniel
diff --git a/catalog.c b/catalog.c
index 6487cb0..7793d21 100644
--- a/catalog.c
+++ b/catalog.c
@@ -64,6 +64,12 @@
static xmlHashTablePtr xmlDefaultCatalog;
+/* Catalog stack */
+const char * catalTab[10]; /* stack of catals */
+const char * catal; /* Current catal stream */
+int catalNr = 0; /* Number of current catal streams */
+int catalMax = 10; /* Max number of catal streams */
+
/************************************************************************
* *
* alloc or dealloc *
@@ -81,8 +87,8 @@
return(NULL);
}
ret->type = type;
- ret->name = name;
- ret->value = value;
+ ret->name = xmlStrdup(name);
+ ret->value = xmlStrdup(value);
return(ret);
}
@@ -193,7 +199,7 @@
if (cur[0] == 0) {
return(NULL);
}
- return(cur);
+ return(cur + 2);
}
static const xmlChar *
@@ -289,6 +295,7 @@
xmlParseCatalog(const xmlChar *value, const char *file) {
const xmlChar *cur = value;
xmlChar *base = NULL;
+ int res;
if ((cur == NULL) || (file == NULL))
return(-1);
@@ -348,9 +355,11 @@
/* error */
break;
}
+ xmlFree(name);
continue;
}
xmlFree(name);
+ name = NULL;
switch(type) {
case XML_CATA_ENTITY:
@@ -417,28 +426,39 @@
} else if (type == XML_CATA_BASE) {
if (base != NULL)
xmlFree(base);
- base = sysid;
+ base = xmlStrdup(sysid);
} else if ((type == XML_CATA_PUBLIC) ||
(type == XML_CATA_SYSTEM)) {
xmlChar *filename;
filename = xmlBuildURI(sysid, base);
if (filename != NULL) {
+ xmlCatalogEntryPtr entry;
- xmlHashAddEntry(xmlDefaultCatalog, name,
- xmlNewCatalogEntry(type, name, filename));
+ entry = xmlNewCatalogEntry(type, name, filename);
+ res = xmlHashAddEntry(xmlDefaultCatalog, name, entry);
+ if (res < 0) {
+ xmlFreeCatalogEntry(entry);
+ }
+ xmlFree(filename);
}
- if (sysid != NULL)
- xmlFree(sysid);
- } else {
- /*
- * drop anything else we won't handle it
- */
- if (name != NULL)
- xmlFree(name);
- if (sysid != NULL)
- xmlFree(sysid);
+
+ } else if (type == XML_CATA_CATALOG) {
+ xmlChar *filename;
+
+ filename = xmlBuildURI(sysid, base);
+ if (filename != NULL) {
+ xmlLoadCatalog((const char *)filename);
+ xmlFree(filename);
+ }
}
+ /*
+ * drop anything else we won't handle it
+ */
+ if (name != NULL)
+ xmlFree(name);
+ if (sysid != NULL)
+ xmlFree(sysid);
}
}
if (base != NULL)
@@ -460,17 +480,20 @@
*
* Load the catalog and makes its definition effective for the default
* external entity loader.
+ * TODO: this function is not thread safe, catalog initialization should
+ * be done once at startup
*
* Returns 0 in case of success -1 in case of error
*/
int
xmlLoadCatalog(const char *filename) {
- int fd, len, ret;
+ int fd, len, ret, i;
struct stat info;
xmlChar *content;
if (filename == NULL)
return(-1);
+
if (xmlDefaultCatalog == NULL)
xmlDefaultCatalog = xmlHashCreate(20);
if (xmlDefaultCatalog == NULL)
@@ -479,17 +502,41 @@
if (stat(filename, &info) < 0)
return(-1);
- if ((fd = open(filename, O_RDONLY)) < 0)
+ /*
+ * Prevent loops
+ */
+ for (i = 0;i < catalNr;i++) {
+ if (xmlStrEqual(catalTab[i], filename)) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlLoadCatalog: %s seems to induce a loop\n",
+ filename);
+ return(-1);
+ }
+ }
+ if (catalNr >= catalMax) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlLoadCatalog: %s catalog list too deep\n",
+ filename);
+ return(-1);
+ }
+ catalTab[catalNr++] = filename;
+
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ catalNr--;
return(-1);
+ }
content = xmlMalloc(info.st_size + 10);
if (content == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %d byte failed\n", info.st_size + 10);
+ catalNr--;
+ return(-1);
}
len = read(fd, content, info.st_size);
if (len < 0) {
xmlFree(content);
+ catalNr--;
return(-1);
}
content[len] = 0;
@@ -497,6 +544,7 @@
ret = xmlParseCatalog(content, filename);
xmlFree(content);
+ catalNr--;
return(ret);
}