1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-08-29 01:49:22 +03:00

Fix xmlBuildRelativeURI for URIs starting with './'

If the relative URI started with './', the 'pos' index was increased
which also affected indexing into the base path. Aside from producing
wrong results, this could also lead to a heap overread of the base
path buffer. The data read from beyond the buffer was only compared
to some char values, so this is mostly harmless.

Inside libxml2, xmlBuildRelativeURI is only called from xinclude.c.

Found with libFuzzer and ASan.
This commit is contained in:
Nick Wellnhofer
2017-06-08 18:25:30 +02:00
parent 45ce1ee399
commit 91e5496780

32
uri.c
View File

@ -2163,7 +2163,6 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
xmlChar *val = NULL;
int ret;
int ix;
int pos = 0;
int nbslash = 0;
int len;
xmlURIPtr ref = NULL;
@ -2254,19 +2253,22 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
uptr = NULL;
len = 1; /* this is for a string terminator only */
} else {
/*
* Next we compare the two strings and find where they first differ
*/
if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/'))
pos += 2;
xmlChar *rptr = (xmlChar *) ref->path;
int pos = 0;
/*
* Next we compare the two strings and find where they first differ
*/
if ((*rptr == '.') && (rptr[1] == '/'))
rptr += 2;
if ((*bptr == '.') && (bptr[1] == '/'))
bptr += 2;
else if ((*bptr == '/') && (ref->path[pos] != '/'))
else if ((*bptr == '/') && (*rptr != '/'))
bptr++;
while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0))
while ((bptr[pos] == rptr[pos]) && (bptr[pos] != 0))
pos++;
if (bptr[pos] == ref->path[pos]) {
if (bptr[pos] == rptr[pos]) {
val = xmlStrdup(BAD_CAST "");
goto done; /* (I can't imagine why anyone would do this) */
}
@ -2276,25 +2278,25 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
* beginning of the "unique" suffix of URI
*/
ix = pos;
if ((ref->path[ix] == '/') && (ix > 0))
if ((rptr[ix] == '/') && (ix > 0))
ix--;
else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/'))
else if ((rptr[ix] == 0) && (ix > 1) && (rptr[ix - 1] == '/'))
ix -= 2;
for (; ix > 0; ix--) {
if (ref->path[ix] == '/')
if (rptr[ix] == '/')
break;
}
if (ix == 0) {
uptr = (xmlChar *)ref->path;
uptr = (xmlChar *)rptr;
} else {
ix++;
uptr = (xmlChar *)&ref->path[ix];
uptr = (xmlChar *)&rptr[ix];
}
/*
* In base, count the number of '/' from the differing point
*/
if (bptr[pos] != ref->path[pos]) {/* check for trivial URI == base */
if (bptr[pos] != rptr[pos]) {/* check for trivial URI == base */
for (; bptr[ix] != 0; ix++) {
if (bptr[ix] == '/')
nbslash++;