Cast to an unsigned type before negating
[openssl.git] / crypto / bio / b_print.c
index 36400cda5e9deff690878fdfcf18fab56240e82a..a46d8b160a9a97fad96bd31a08183708b65dfd34 100644 (file)
@@ -10,7 +10,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
-#include <limits.h>
+#include "internal/numbers.h"
 #include "internal/cryptlib.h"
 #ifndef NO_SYS_TYPES_H
 # include <sys/types.h>
@@ -363,9 +363,15 @@ _dopr(char **sbuffer,
             break;
         }
     }
-    *truncated = (currlen > *maxlen - 1);
-    if (*truncated)
-        currlen = *maxlen - 1;
+    /*
+     * We have to truncate if there is no dynamic buffer and we have filled the
+     * static buffer.
+     */
+    if (buffer == NULL) {
+        *truncated = (currlen > *maxlen - 1);
+        if (*truncated)
+            currlen = *maxlen - 1;
+    }
     if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
         return 0;
     *retlen = currlen - 1;
@@ -385,28 +391,37 @@ fmtstr(char **sbuffer,
     if (value == 0)
         value = "<NULL>";
 
-    strln = strlen(value);
-    if (strln > INT_MAX)
-        strln = INT_MAX;
+    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
 
     padlen = min - strln;
     if (min < 0 || padlen < 0)
         padlen = 0;
+    if (max >= 0) {
+        /*
+         * Calculate the maximum output including padding.
+         * Make sure max doesn't overflow into negativity
+         */
+        if (max < INT_MAX - padlen)
+            max += padlen;
+        else
+            max = INT_MAX;
+    }
     if (flags & DP_F_MINUS)
         padlen = -padlen;
 
-    while ((padlen > 0) && (cnt < max)) {
+    while ((padlen > 0) && (max < 0 || cnt < max)) {
         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
             return 0;
         --padlen;
         ++cnt;
     }
-    while (*value && (cnt < max)) {
+    while (strln > 0 && (max < 0 || cnt < max)) {
         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
             return 0;
+        --strln;
         ++cnt;
     }
-    while ((padlen < 0) && (cnt < max)) {
+    while ((padlen < 0) && (max < 0 || cnt < max)) {
         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
             return 0;
         ++padlen;
@@ -436,7 +451,7 @@ fmtint(char **sbuffer,
     if (!(flags & DP_F_UNSIGNED)) {
         if (value < 0) {
             signvalue = '-';
-            uvalue = -value;
+            uvalue = -(unsigned LLONG)value;
         } else if (flags & DP_F_PLUS)
             signvalue = '+';
         else if (flags & DP_F_SPACE)
@@ -561,9 +576,9 @@ fmtfp(char **sbuffer,
     int padlen = 0;
     int zpadlen = 0;
     long exp = 0;
-    long intpart;
-    long fracpart;
-    long max10;
+    unsigned long intpart;
+    unsigned long fracpart;
+    unsigned long max10;
     int realstyle;
 
     if (max < 0)
@@ -638,7 +653,11 @@ fmtfp(char **sbuffer,
             fvalue = tmpvalue;
     }
     ufvalue = abs_val(fvalue);
-    intpart = (long)ufvalue;
+    if (ufvalue > ULONG_MAX) {
+        /* Number too big */
+        return 0;
+    }
+    intpart = (unsigned long)ufvalue;
 
     /*
      * sorry, we only support 9 digits past the decimal because of our