Imported Upstream version 2.9.1
[platform/upstream/libxml2.git] / uri.c
diff --git a/uri.c b/uri.c
index 7e2f525..4ab0ce2 100644 (file)
--- a/uri.c
+++ b/uri.c
@@ -1,12 +1,10 @@
 /**
- * uri.c: set of generic URI related routines 
+ * uri.c: set of generic URI related routines
  *
  * Reference: RFCs 3986, 2732 and 2373
  *
  * See Copyright for the status of this software.
  *
- * TODO: that module behaves really badly on OOM situation
- *
  * daniel@veillard.com
  */
 
 #include <libxml/globals.h>
 #include <libxml/xmlerror.h>
 
+/**
+ * MAX_URI_LENGTH:
+ *
+ * The definition of the URI regexp in the above RFC has no size limit
+ * In practice they are usually relativey short except for the
+ * data URI scheme as defined in RFC 2397. Even for data URI the usual
+ * maximum size before hitting random practical limits is around 64 KB
+ * and 4KB is usually a maximum admitted limit for proper operations.
+ * The value below is more a security limit than anything else and
+ * really should never be hit by 'normal' operations
+ * Set to 1 MByte in 2012, this is only enforced on output
+ */
+#define MAX_URI_LENGTH 1024 * 1024
+
+static void
+xmlURIErrMemory(const char *extra)
+{
+    if (extra)
+        __xmlRaiseError(NULL, NULL, NULL,
+                        NULL, NULL, XML_FROM_URI,
+                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
+                        extra, NULL, NULL, 0, 0,
+                        "Memory allocation failed : %s\n", extra);
+    else
+        __xmlRaiseError(NULL, NULL, NULL,
+                        NULL, NULL, XML_FROM_URI,
+                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
+                        NULL, NULL, NULL, 0, 0,
+                        "Memory allocation failed\n");
+}
+
 static void xmlCleanURI(xmlURIPtr uri);
 
 /*
@@ -982,8 +1011,7 @@ xmlCreateURI(void) {
 
     ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI));
     if (ret == NULL) {
-       xmlGenericError(xmlGenericErrorContext,
-               "xmlCreateURI: out of memory\n");
+        xmlURIErrMemory("creating URI structure\n");
        return(NULL);
     }
     memset(ret, 0, sizeof(xmlURI));
@@ -991,6 +1019,31 @@ xmlCreateURI(void) {
 }
 
 /**
+ * xmlSaveUriRealloc:
+ *
+ * Function to handle properly a reallocation when saving an URI
+ * Also imposes some limit on the length of an URI string output
+ */
+static xmlChar *
+xmlSaveUriRealloc(xmlChar *ret, int *max) {
+    xmlChar *temp;
+    int tmp;
+
+    if (*max > MAX_URI_LENGTH) {
+        xmlURIErrMemory("reaching arbitrary MAX_URI_LENGTH limit\n");
+        return(NULL);
+    }
+    tmp = *max * 2;
+    temp = (xmlChar *) xmlRealloc(ret, (tmp + 1));
+    if (temp == NULL) {
+        xmlURIErrMemory("saving URI\n");
+        return(NULL);
+    }
+    *max = tmp;
+    return(temp);
+}
+
+/**
  * xmlSaveUri:
  * @uri:  pointer to an xmlURI
  *
@@ -1012,8 +1065,7 @@ xmlSaveUri(xmlURIPtr uri) {
     max = 80;
     ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar));
     if (ret == NULL) {
-       xmlGenericError(xmlGenericErrorContext,
-               "xmlSaveUri: out of memory\n");
+        xmlURIErrMemory("saving URI\n");
        return(NULL);
     }
     len = 0;
@@ -1022,28 +1074,16 @@ xmlSaveUri(xmlURIPtr uri) {
        p = uri->scheme;
        while (*p != 0) {
            if (len >= max) {
-               max *= 2;
-               temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
-               if (temp == NULL) {
-                   xmlGenericError(xmlGenericErrorContext,
-                           "xmlSaveUri: out of memory\n");
-                   xmlFree(ret);
-                   return(NULL);
-               }
+                temp = xmlSaveUriRealloc(ret, &max);
+                if (temp == NULL) goto mem_error;
                ret = temp;
            }
            ret[len++] = *p++;
        }
        if (len >= max) {
-           max *= 2;
-           temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
-           if (temp == NULL) {
-               xmlGenericError(xmlGenericErrorContext,
-                       "xmlSaveUri: out of memory\n");
-               xmlFree(ret);
-               return(NULL);
-           }
-           ret = temp;
+            temp = xmlSaveUriRealloc(ret, &max);
+            if (temp == NULL) goto mem_error;
+            ret = temp;
        }
        ret[len++] = ':';
     }
@@ -1051,15 +1091,9 @@ xmlSaveUri(xmlURIPtr uri) {
        p = uri->opaque;
        while (*p != 0) {
            if (len + 3 >= max) {
-               max *= 2;
-               temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
-               if (temp == NULL) {
-                   xmlGenericError(xmlGenericErrorContext,
-                           "xmlSaveUri: out of memory\n");
-                   xmlFree(ret);
-                   return(NULL);
-               }
-               ret = temp;
+                temp = xmlSaveUriRealloc(ret, &max);
+                if (temp == NULL) goto mem_error;
+                ret = temp;
            }
            if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p)))
                ret[len++] = *p++;
@@ -1074,15 +1108,9 @@ xmlSaveUri(xmlURIPtr uri) {
     } else {
        if (uri->server != NULL) {
            if (len + 3 >= max) {
-               max *= 2;
-               temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
-               if (temp == NULL) {
-                   xmlGenericError(xmlGenericErrorContext,
-                           "xmlSaveUri: out of memory\n");
-                  xmlFree(ret);  
-                   return(NULL);
-               }
-               ret = temp;
+                temp = xmlSaveUriRealloc(ret, &max);
+                if (temp == NULL) goto mem_error;
+                ret = temp;
            }
            ret[len++] = '/';
            ret[len++] = '/';
@@ -1090,16 +1118,9 @@ xmlSaveUri(xmlURIPtr uri) {
                p = uri->user;
                while (*p != 0) {
                    if (len + 3 >= max) {
-                       max *= 2;
-                       temp = (xmlChar *) xmlRealloc(ret,
-                               (max + 1) * sizeof(xmlChar));
-                       if (temp == NULL) {
-                           xmlGenericError(xmlGenericErrorContext,
-                                   "xmlSaveUri: out of memory\n");
-                           xmlFree(ret);
-                           return(NULL);
-                       }
-                       ret = temp;
+                        temp = xmlSaveUriRealloc(ret, &max);
+                        if (temp == NULL) goto mem_error;
+                        ret = temp;
                    }
                    if ((IS_UNRESERVED(*(p))) ||
                        ((*(p) == ';')) || ((*(p) == ':')) ||
@@ -1116,78 +1137,43 @@ xmlSaveUri(xmlURIPtr uri) {
                    }
                }
                if (len + 3 >= max) {
-                   max *= 2;
-                   temp = (xmlChar *) xmlRealloc(ret,
-                           (max + 1) * sizeof(xmlChar));
-                   if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                       xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                    temp = xmlSaveUriRealloc(ret, &max);
+                    if (temp == NULL) goto mem_error;
+                    ret = temp;
                }
                ret[len++] = '@';
            }
            p = uri->server;
            while (*p != 0) {
                if (len >= max) {
-                   max *= 2;
-                   temp = (xmlChar *) xmlRealloc(ret,
-                           (max + 1) * sizeof(xmlChar));
-                   if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                       xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                    temp = xmlSaveUriRealloc(ret, &max);
+                    if (temp == NULL) goto mem_error;
+                    ret = temp;
                }
                ret[len++] = *p++;
            }
            if (uri->port > 0) {
                if (len + 10 >= max) {
-                   max *= 2;
-                   temp = (xmlChar *) xmlRealloc(ret,
-                           (max + 1) * sizeof(xmlChar));
-                   if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                    temp = xmlSaveUriRealloc(ret, &max);
+                    if (temp == NULL) goto mem_error;
+                    ret = temp;
                }
                len += snprintf((char *) &ret[len], max - len, ":%d", uri->port);
            }
        } else if (uri->authority != NULL) {
            if (len + 3 >= max) {
-               max *= 2;
-               temp = (xmlChar *) xmlRealloc(ret,
-                       (max + 1) * sizeof(xmlChar));
-               if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                temp = xmlSaveUriRealloc(ret, &max);
+                if (temp == NULL) goto mem_error;
+                ret = temp;
            }
            ret[len++] = '/';
            ret[len++] = '/';
            p = uri->authority;
            while (*p != 0) {
                if (len + 3 >= max) {
-                   max *= 2;
-                   temp = (xmlChar *) xmlRealloc(ret,
-                           (max + 1) * sizeof(xmlChar));
-                   if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                    temp = xmlSaveUriRealloc(ret, &max);
+                    if (temp == NULL) goto mem_error;
+                    ret = temp;
                }
                if ((IS_UNRESERVED(*(p))) ||
                     ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) ||
@@ -1204,16 +1190,9 @@ xmlSaveUri(xmlURIPtr uri) {
            }
        } else if (uri->scheme != NULL) {
            if (len + 3 >= max) {
-               max *= 2;
-               temp = (xmlChar *) xmlRealloc(ret,
-                       (max + 1) * sizeof(xmlChar));
-               if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                temp = xmlSaveUriRealloc(ret, &max);
+                if (temp == NULL) goto mem_error;
+                ret = temp;
            }
            ret[len++] = '/';
            ret[len++] = '/';
@@ -1231,14 +1210,9 @@ xmlSaveUri(xmlURIPtr uri) {
                (p[2] == ':') &&
                (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
                if (len + 3 >= max) {
-                   max *= 2;
-                   ret = (xmlChar *) xmlRealloc(ret,
-                           (max + 1) * sizeof(xmlChar));
-                   if (ret == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                       return(NULL);
-                   }
+                    temp = xmlSaveUriRealloc(ret, &max);
+                    if (temp == NULL) goto mem_error;
+                    ret = temp;
                }
                ret[len++] = *p++;
                ret[len++] = *p++;
@@ -1246,16 +1220,9 @@ xmlSaveUri(xmlURIPtr uri) {
            }
            while (*p != 0) {
                if (len + 3 >= max) {
-                   max *= 2;
-                   temp = (xmlChar *) xmlRealloc(ret,
-                           (max + 1) * sizeof(xmlChar));
-                   if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                    temp = xmlSaveUriRealloc(ret, &max);
+                    if (temp == NULL) goto mem_error;
+                    ret = temp;
                }
                if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) ||
                     ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) ||
@@ -1273,63 +1240,35 @@ xmlSaveUri(xmlURIPtr uri) {
        }
        if (uri->query_raw != NULL) {
            if (len + 1 >= max) {
-               max *= 2;
-               temp = (xmlChar *) xmlRealloc(ret,
-                       (max + 1) * sizeof(xmlChar));
-               if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                temp = xmlSaveUriRealloc(ret, &max);
+                if (temp == NULL) goto mem_error;
+                ret = temp;
            }
            ret[len++] = '?';
            p = uri->query_raw;
            while (*p != 0) {
                if (len + 1 >= max) {
-                   max *= 2;
-                   temp = (xmlChar *) xmlRealloc(ret,
-                           (max + 1) * sizeof(xmlChar));
-                   if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                    temp = xmlSaveUriRealloc(ret, &max);
+                    if (temp == NULL) goto mem_error;
+                    ret = temp;
                }
                ret[len++] = *p++;
            }
        } else if (uri->query != NULL) {
            if (len + 3 >= max) {
-               max *= 2;
-               temp = (xmlChar *) xmlRealloc(ret,
-                       (max + 1) * sizeof(xmlChar));
-               if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                temp = xmlSaveUriRealloc(ret, &max);
+                if (temp == NULL) goto mem_error;
+                ret = temp;
            }
            ret[len++] = '?';
            p = uri->query;
            while (*p != 0) {
                if (len + 3 >= max) {
-                   max *= 2;
-                   temp = (xmlChar *) xmlRealloc(ret,
-                           (max + 1) * sizeof(xmlChar));
-                   if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                    temp = xmlSaveUriRealloc(ret, &max);
+                    if (temp == NULL) goto mem_error;
+                    ret = temp;
                }
-               if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) 
+               if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
                    ret[len++] = *p++;
                else {
                    int val = *(unsigned char *)p++;
@@ -1343,33 +1282,19 @@ xmlSaveUri(xmlURIPtr uri) {
     }
     if (uri->fragment != NULL) {
        if (len + 3 >= max) {
-           max *= 2;
-           temp = (xmlChar *) xmlRealloc(ret,
-                   (max + 1) * sizeof(xmlChar));
-           if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+            temp = xmlSaveUriRealloc(ret, &max);
+            if (temp == NULL) goto mem_error;
+            ret = temp;
        }
        ret[len++] = '#';
        p = uri->fragment;
        while (*p != 0) {
            if (len + 3 >= max) {
-               max *= 2;
-               temp = (xmlChar *) xmlRealloc(ret,
-                       (max + 1) * sizeof(xmlChar));
-               if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+                temp = xmlSaveUriRealloc(ret, &max);
+                if (temp == NULL) goto mem_error;
+                ret = temp;
            }
-           if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) 
+           if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
                ret[len++] = *p++;
            else {
                int val = *(unsigned char *)p++;
@@ -1381,18 +1306,16 @@ xmlSaveUri(xmlURIPtr uri) {
        }
     }
     if (len >= max) {
-       max *= 2;
-       temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
-       if (temp == NULL) {
-                       xmlGenericError(xmlGenericErrorContext,
-                               "xmlSaveUri: out of memory\n");
-                     xmlFree(ret);
-                       return(NULL);
-                   }
-                   ret = temp;
+        temp = xmlSaveUriRealloc(ret, &max);
+        if (temp == NULL) goto mem_error;
+        ret = temp;
     }
     ret[len] = 0;
     return(ret);
+
+mem_error:
+    xmlFree(ret);
+    return(NULL);
 }
 
 /**
@@ -1695,8 +1618,7 @@ xmlURIUnescapeString(const char *str, int len, char *target) {
     if (target == NULL) {
        ret = (char *) xmlMallocAtomic(len + 1);
        if (ret == NULL) {
-           xmlGenericError(xmlGenericErrorContext,
-                   "xmlURIUnescapeString: out of memory\n");
+            xmlURIErrMemory("unescaping URI value\n");
            return(NULL);
        }
     } else
@@ -1706,14 +1628,14 @@ xmlURIUnescapeString(const char *str, int len, char *target) {
     while(len > 0) {
        if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) {
            in++;
-           if ((*in >= '0') && (*in <= '9')) 
+           if ((*in >= '0') && (*in <= '9'))
                *out = (*in - '0');
            else if ((*in >= 'a') && (*in <= 'f'))
                *out = (*in - 'a') + 10;
            else if ((*in >= 'A') && (*in <= 'F'))
                *out = (*in - 'A') + 10;
            in++;
-           if ((*in >= '0') && (*in <= '9')) 
+           if ((*in >= '0') && (*in <= '9'))
                *out = *out * 16 + (*in - '0');
            else if ((*in >= 'a') && (*in <= 'f'))
                *out = *out * 16 + (*in - 'a') + 10;
@@ -1746,8 +1668,7 @@ xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) {
     xmlChar *ret, ch;
     xmlChar *temp;
     const xmlChar *in;
-
-    unsigned int len, out;
+    int len, out;
 
     if (str == NULL)
        return(NULL);
@@ -1759,19 +1680,16 @@ xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) {
     len += 20;
     ret = (xmlChar *) xmlMallocAtomic(len);
     if (ret == NULL) {
-       xmlGenericError(xmlGenericErrorContext,
-               "xmlURIEscapeStr: out of memory\n");
+        xmlURIErrMemory("escaping URI value\n");
        return(NULL);
     }
     in = (const xmlChar *) str;
     out = 0;
     while(*in != 0) {
        if (len - out <= 3) {
-           len += 20;
-           temp = (xmlChar *) xmlRealloc(ret, len);
+            temp = xmlSaveUriRealloc(ret, &len);
            if (temp == NULL) {
-               xmlGenericError(xmlGenericErrorContext,
-                       "xmlURIEscapeStr: out of memory\n");
+                xmlURIErrMemory("escaping URI value\n");
                xmlFree(ret);
                return(NULL);
            }
@@ -1826,10 +1744,9 @@ xmlURIEscape(const xmlChar * str)
     int ret2;
 
 #define NULLCHK(p) if(!p) { \
-                   xmlGenericError(xmlGenericErrorContext, \
-                        "xmlURIEscape: out of memory\n"); \
-                        xmlFreeURI(uri); \
-                        return NULL; } \
+         xmlURIErrMemory("escaping URI value\n"); \
+         xmlFreeURI(uri); \
+         return NULL; } \
 
     if (str == NULL)
         return (NULL);
@@ -1872,7 +1789,7 @@ xmlURIEscape(const xmlChar * str)
     if (uri->user) {
         segment = xmlURIEscapeStr(BAD_CAST uri->user, BAD_CAST ";:&=+$,");
         NULLCHK(segment)
-               ret = xmlStrcat(ret,BAD_CAST "//");     
+               ret = xmlStrcat(ret,BAD_CAST "//");
         ret = xmlStrcat(ret, segment);
         ret = xmlStrcat(ret, BAD_CAST "@");
         xmlFree(segment);
@@ -1950,7 +1867,7 @@ xmlURIEscape(const xmlChar * str)
  *
  * Computes he final URI of the reference done by checking that
  * the given URI is valid, and building the final URI using the
- * base URI. This is processed according to section 5.2 of the 
+ * base URI. This is processed according to section 5.2 of the
  * RFC 2396
  *
  * 5.2. Resolving Relative References to Absolute Form
@@ -1974,7 +1891,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
      *    as a reference to "." rather than as a synonym for the current
      *    URI.  Should we do that here?
      */
-    if (URI == NULL) 
+    if (URI == NULL)
        ret = -1;
     else {
        if (*URI) {
@@ -2045,7 +1962,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
            res->server = xmlMemStrdup(bas->server);
            if (bas->user != NULL)
                res->user = xmlMemStrdup(bas->user);
-           res->port = bas->port;              
+           res->port = bas->port;
        }
        if (bas->path != NULL)
            res->path = xmlMemStrdup(bas->path);
@@ -2074,7 +1991,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
     }
     if (bas->scheme != NULL)
        res->scheme = xmlMemStrdup(bas->scheme);
+
     if (ref->query_raw != NULL)
        res->query_raw = xmlMemStrdup(ref->query_raw);
     else if (ref->query != NULL)
@@ -2096,7 +2013,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
            res->server = xmlMemStrdup(ref->server);
            if (ref->user != NULL)
                res->user = xmlMemStrdup(ref->user);
-            res->port = ref->port;             
+            res->port = ref->port;
        }
        if (ref->path != NULL)
            res->path = xmlMemStrdup(ref->path);
@@ -2108,7 +2025,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
        res->server = xmlMemStrdup(bas->server);
        if (bas->user != NULL)
            res->user = xmlMemStrdup(bas->user);
-       res->port = bas->port;          
+       res->port = bas->port;
     }
 
     /*
@@ -2136,8 +2053,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
        len += strlen(bas->path);
     res->path = (char *) xmlMallocAtomic(len);
     if (res->path == NULL) {
-       xmlGenericError(xmlGenericErrorContext,
-               "xmlBuildURI: out of memory\n");
+        xmlURIErrMemory("resolving URI against base\n");
        goto done;
     }
     res->path[0] = 0;
@@ -2383,7 +2299,7 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
        }
        len = xmlStrlen (uptr) + 1;
     }
-    
+
     if (nbslash == 0) {
        if (uptr != NULL)
            /* exception characters from xmlSaveUri */
@@ -2398,8 +2314,7 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
      */
     val = (xmlChar *) xmlMalloc (len + 3 * nbslash);
     if (val == NULL) {
-       xmlGenericError(xmlGenericErrorContext,
-               "xmlBuildRelativeURI: out of memory\n");
+        xmlURIErrMemory("building relative URI\n");
        goto done;
     }
     vptr = val;
@@ -2451,14 +2366,14 @@ done:
  * xmlCanonicPath:
  * @path:  the resource locator in a filesystem notation
  *
- * Constructs a canonic path from the specified path. 
+ * Constructs a canonic path from the specified path.
  *
- * Returns a new canonic path, or a duplicate of the path parameter if the 
+ * Returns a new canonic path, or a duplicate of the path parameter if the
  * construction fails. The caller is responsible for freeing the memory occupied
- * by the returned string. If there is insufficient memory available, or the 
+ * by the returned string. If there is insufficient memory available, or the
  * argument is NULL, the function returns NULL.
  */
-#define IS_WINDOWS_PATH(p)                                     \
+#define IS_WINDOWS_PATH(p)                                     \
        ((p != NULL) &&                                         \
         (((p[0] >= 'a') && (p[0] <= 'z')) ||                   \
          ((p[0] >= 'A') && (p[0] <= 'Z'))) &&                  \
@@ -2470,7 +2385,7 @@ xmlCanonicPath(const xmlChar *path)
  * For Windows implementations, additional work needs to be done to
  * replace backslashes in pathnames with "forward slashes"
  */
-#if defined(_WIN32) && !defined(__CYGWIN__)    
+#if defined(_WIN32) && !defined(__CYGWIN__)
     int len = 0;
     int i = 0;
     xmlChar *p = NULL;
@@ -2482,7 +2397,20 @@ xmlCanonicPath(const xmlChar *path)
     if (path == NULL)
        return(NULL);
 
-    /* sanitize filename starting with // so it can be used as URI */
+#if defined(_WIN32)
+    /*
+     * We must not change the backslashes to slashes if the the path
+     * starts with \\?\
+     * Those paths can be up to 32k characters long.
+     * Was added specifically for OpenOffice, those paths can't be converted
+     * to URIs anyway.
+     */
+    if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
+        (path[3] == '\\') )
+       return xmlStrdup((const xmlChar *) path);
+#endif
+
+       /* sanitize filename starting with // so it can be used as URI */
     if ((path[0] == '/') && (path[1] == '/') && (path[2] != '/'))
         path++;
 
@@ -2529,7 +2457,7 @@ xmlCanonicPath(const xmlChar *path)
 
 path_processing:
 /* For Windows implementations, replace backslashes with 'forward slashes' */
-#if defined(_WIN32) && !defined(__CYGWIN__)    
+#if defined(_WIN32) && !defined(__CYGWIN__)
     /*
      * Create a URI structure
      */
@@ -2586,7 +2514,7 @@ path_processing:
  *
  * Constructs an URI expressing the existing path
  *
- * Returns a new URI, or a duplicate of the path parameter if the 
+ * Returns a new URI, or a duplicate of the path parameter if the
  * construction fails. The caller is responsible for freeing the memory
  * occupied by the returned string. If there is insufficient memory available,
  * or the argument is NULL, the function returns NULL.
@@ -2609,7 +2537,7 @@ xmlPathToURI(const xmlChar *path)
     if (cal == NULL)
         return(NULL);
 #if defined(_WIN32) && !defined(__CYGWIN__)
-    /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?) 
+    /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?)
        If 'cal' is a valid URI allready then we are done here, as continuing would make
        it invalid. */
     if ((uri = xmlParseURI((const char *) cal)) != NULL) {