From f9fce963132b2a56a0f91bc19223a5c60f9786cb Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 16 May 2019 21:16:01 +0200
Subject: [PATCH 34/37] Fix unsigned integer overflow

It's defined behavior but -fsanitize=unsigned-integer-overflow is
useful to discover bugs.
---
 parser.c                       | 34 ++++++++++++++++++++--------------
 result/errors/charref1.xml.err |  2 +-
 result/errors/charref1.xml.str |  2 +-
 timsort.h                      |  3 ++-
 uri.c                          |  6 ++++--
 5 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/parser.c b/parser.c
index 2cab92c..459502b 100644
--- a/parser.c
+++ b/parser.c
@@ -2281,9 +2281,8 @@ xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
  */
 int
 xmlParseCharRef(xmlParserCtxtPtr ctxt) {
-    unsigned int val = 0;
+    int val = 0;
     int count = 0;
-    unsigned int outofrange = 0;
 
     /*
      * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
@@ -2310,8 +2309,8 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
 		val = 0;
 		break;
 	    }
-	    if (val > 0x10FFFF)
-	        outofrange = val;
+	    if (val > 0x110000)
+	        val = 0x110000;
 
 	    NEXT;
 	    count++;
@@ -2339,8 +2338,8 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
 		val = 0;
 		break;
 	    }
-	    if (val > 0x10FFFF)
-	        outofrange = val;
+	    if (val > 0x110000)
+	        val = 0x110000;
 
 	    NEXT;
 	    count++;
@@ -2360,7 +2359,11 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
      * Characters referred to using character references must match the
      * production for Char.
      */
-    if ((IS_CHAR(val) && (outofrange == 0))) {
+    if (val >= 0x110000) {
+        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
+                "xmlParseCharRef: character reference out of bounds\n",
+	        val);
+    } else if (IS_CHAR(val)) {
         return(val);
     } else {
         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
@@ -2392,8 +2395,7 @@ static int
 xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
     const xmlChar *ptr;
     xmlChar cur;
-    unsigned int val = 0;
-    unsigned int outofrange = 0;
+    int val = 0;
 
     if ((str == NULL) || (*str == NULL)) return(0);
     ptr = *str;
@@ -2413,8 +2415,8 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
 		val = 0;
 		break;
 	    }
-	    if (val > 0x10FFFF)
-	        outofrange = val;
+	    if (val > 0x110000)
+	        val = 0x110000;
 
 	    ptr++;
 	    cur = *ptr;
@@ -2432,8 +2434,8 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
 		val = 0;
 		break;
 	    }
-	    if (val > 0x10FFFF)
-	        outofrange = val;
+	    if (val > 0x110000)
+	        val = 0x110000;
 
 	    ptr++;
 	    cur = *ptr;
@@ -2451,7 +2453,11 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
      * Characters referred to using character references must match the
      * production for Char.
      */
-    if ((IS_CHAR(val) && (outofrange == 0))) {
+    if (val >= 0x110000) {
+        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
+                "xmlParseStringCharRef: character reference out of bounds\n",
+                val);
+    } else if (IS_CHAR(val)) {
         return(val);
     } else {
         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
diff --git a/result/errors/charref1.xml.err b/result/errors/charref1.xml.err
index aa43bcf..dbf3005 100644
--- a/result/errors/charref1.xml.err
+++ b/result/errors/charref1.xml.err
@@ -1,3 +1,3 @@
-./test/errors/charref1.xml:1: parser error : xmlParseCharRef: invalid xmlChar value 60
+./test/errors/charref1.xml:1: parser error : xmlParseCharRef: character reference out of bounds
 <bla>&#010100000000000000000000000000000000000000000000000060;</bla>
                                                               ^
diff --git a/result/errors/charref1.xml.str b/result/errors/charref1.xml.str
index 467b4f6..692f614 100644
--- a/result/errors/charref1.xml.str
+++ b/result/errors/charref1.xml.str
@@ -1,4 +1,4 @@
-./test/errors/charref1.xml:1: parser error : xmlParseCharRef: invalid xmlChar value 60
+./test/errors/charref1.xml:1: parser error : xmlParseCharRef: character reference out of bounds
 <bla>&#010100000000000000000000000000000000000000000000000060;</bla>
                                                               ^
 ./test/errors/charref1.xml : failed to parse
diff --git a/timsort.h b/timsort.h
index e841bd9..622705b 100644
--- a/timsort.h
+++ b/timsort.h
@@ -404,7 +404,8 @@ static void TIM_SORT_MERGE(SORT_TYPE *dst, const TIM_SORT_RUN_T *stack, const in
     j = curr + A;
     k = curr + A + B;
 
-    while (k-- > curr) {
+    while (k > curr) {
+      k--;
       if ((i > 0) && (j > curr)) {
         if (SORT_CMP(dst[j - 1], storage[i - 1]) > 0) {
           dst[k] = dst[--j];
diff --git a/uri.c b/uri.c
index 2cf8d9f..9772aaf 100644
--- a/uri.c
+++ b/uri.c
@@ -325,16 +325,18 @@ static int
 xmlParse3986Port(xmlURIPtr uri, const char **str)
 {
     const char *cur = *str;
-    unsigned port = 0; /* unsigned for defined overflow behavior */
+    int port = 0;
 
     if (ISA_DIGIT(cur)) {
 	while (ISA_DIGIT(cur)) {
 	    port = port * 10 + (*cur - '0');
+            if (port > 99999999)
+                port = 99999999;
 
 	    cur++;
 	}
 	if (uri != NULL)
-	    uri->port = port & INT_MAX; /* port value modulo INT_MAX+1 */
+	    uri->port = port;
 	*str = cur;
 	return(0);
     }
-- 
1.8.3.1

