diff -up openssl-1.0.1e/crypto/bio/b_print.c.bio-printf openssl-1.0.1e/crypto/bio/b_print.c --- openssl-1.0.1e/crypto/bio/b_print.c.bio-printf 2013-02-11 16:26:04.000000000 +0100 +++ openssl-1.0.1e/crypto/bio/b_print.c 2016-04-07 14:36:55.538117697 +0200 @@ -125,14 +125,14 @@ #define LLONG long #endif -static void fmtstr (char **, char **, size_t *, size_t *, +static int fmtstr(char **, char **, size_t *, size_t *, const char *, int, int, int); -static void fmtint (char **, char **, size_t *, size_t *, +static int fmtint(char **, char **, size_t *, size_t *, LLONG, int, int, int, int); -static void fmtfp (char **, char **, size_t *, size_t *, +static int fmtfp(char **, char **, size_t *, size_t *, LDOUBLE, int, int, int); -static void doapr_outch (char **, char **, size_t *, size_t *, int); -static void _dopr(char **sbuffer, char **buffer, +static int doapr_outch(char **, char **, size_t *, size_t *, int); +static int _dopr(char **sbuffer, char **buffer, size_t *maxlen, size_t *retlen, int *truncated, const char *format, va_list args); @@ -165,7 +165,7 @@ static void _dopr(char **sbuffer, char * #define char_to_int(p) (p - '0') #define OSSL_MAX(p,q) ((p >= q) ? p : q) -static void +static int _dopr( char **sbuffer, char **buffer, @@ -200,7 +200,8 @@ _dopr( if (ch == '%') state = DP_S_FLAGS; else - doapr_outch(sbuffer,buffer, &currlen, maxlen, ch); + if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) + return 0; ch = *format++; break; case DP_S_FLAGS: @@ -306,8 +307,9 @@ _dopr( value = va_arg(args, int); break; } - fmtint(sbuffer, buffer, &currlen, maxlen, - value, 10, min, max, flags); + if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, + max, flags)) + return 0; break; case 'X': flags |= DP_F_UP; @@ -332,17 +334,19 @@ _dopr( unsigned int); break; } - fmtint(sbuffer, buffer, &currlen, maxlen, value, + if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), - min, max, flags); + min, max, flags)) + return 0; break; case 'f': if (cflags == DP_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); else fvalue = va_arg(args, double); - fmtfp(sbuffer, buffer, &currlen, maxlen, - fvalue, min, max, flags); + if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, + flags)) + return 0; break; case 'E': flags |= DP_F_UP; @@ -361,8 +365,9 @@ _dopr( fvalue = va_arg(args, double); break; case 'c': - doapr_outch(sbuffer, buffer, &currlen, maxlen, - va_arg(args, int)); + if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, + va_arg(args, int))) + return 0; break; case 's': strvalue = va_arg(args, char *); @@ -372,13 +377,15 @@ _dopr( else max = *maxlen; } - fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, - flags, min, max); + if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, + flags, min, max)) + return 0; break; case 'p': value = (long)va_arg(args, void *); - fmtint(sbuffer, buffer, &currlen, maxlen, - value, 16, min, max, flags|DP_F_NUM); + if (!fmtint(sbuffer, buffer, &currlen, maxlen, + value, 16, min, max, flags | DP_F_NUM)) + return 0; break; case 'n': /* XXX */ if (cflags == DP_C_SHORT) { @@ -400,7 +407,8 @@ _dopr( } break; case '%': - doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); + if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) + return 0; break; case 'w': /* not supported yet, treat as next char */ @@ -424,12 +432,13 @@ _dopr( *truncated = (currlen > *maxlen - 1); if (*truncated) currlen = *maxlen - 1; - doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'); + if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) + return 0; *retlen = currlen - 1; - return; + return 1; } -static void +static int fmtstr( char **sbuffer, char **buffer, @@ -440,36 +449,44 @@ fmtstr( int min, int max) { - int padlen, strln; + int padlen; + size_t strln; int cnt = 0; if (value == 0) value = ""; - for (strln = 0; value[strln]; ++strln) - ; + + strln = strlen(value); + if (strln > INT_MAX) + strln = INT_MAX; + padlen = min - strln; - if (padlen < 0) + if (min < 0 || padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; while ((padlen > 0) && (cnt < max)) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; --padlen; ++cnt; } while (*value && (cnt < max)) { - doapr_outch(sbuffer, buffer, currlen, maxlen, *value++); + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) + return 0; ++cnt; } while ((padlen < 0) && (cnt < max)) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; ++padlen; ++cnt; } + return 1; } -static void +static int fmtint( char **sbuffer, char **buffer, @@ -533,37 +550,44 @@ fmtint( /* spaces */ while (spadlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; --spadlen; } /* sign */ if (signvalue) - doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; /* prefix */ while (*prefix) { - doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix); + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) + return 0; prefix++; } /* zeros */ if (zpadlen > 0) { while (zpadlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; --zpadlen; } } /* digits */ - while (place > 0) - doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]); + while (place > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) + return 0; + } /* left justified spaces */ while (spadlen < 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; ++spadlen; } - return; + return 1; } static LDOUBLE @@ -597,7 +621,7 @@ roundv(LDOUBLE value) return intpart; } -static void +static int fmtfp( char **sbuffer, char **buffer, @@ -616,7 +640,6 @@ fmtfp( int fplace = 0; int padlen = 0; int zpadlen = 0; - int caps = 0; long intpart; long fracpart; long max10; @@ -650,9 +673,7 @@ fmtfp( /* convert integer part */ do { - iconvert[iplace++] = - (caps ? "0123456789ABCDEF" - : "0123456789abcdef")[intpart % 10]; + iconvert[iplace++] = "0123456789"[intpart % 10]; intpart = (intpart / 10); } while (intpart && (iplace < (int)sizeof(iconvert))); if (iplace == sizeof iconvert) @@ -661,9 +682,7 @@ fmtfp( /* convert fractional part */ do { - fconvert[fplace++] = - (caps ? "0123456789ABCDEF" - : "0123456789abcdef")[fracpart % 10]; + fconvert[fplace++] = "0123456789"[fracpart % 10]; fracpart = (fracpart / 10); } while (fplace < max); if (fplace == sizeof fconvert) @@ -682,47 +701,61 @@ fmtfp( if ((flags & DP_F_ZERO) && (padlen > 0)) { if (signvalue) { - doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; --padlen; signvalue = 0; } while (padlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; --padlen; } } while (padlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; --padlen; } - if (signvalue) - doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); + if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; - while (iplace > 0) - doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]); + while (iplace > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) + return 0; + } /* * Decimal point. This should probably use locale to find the correct * char to print out. */ if (max > 0 || (flags & DP_F_NUM)) { - doapr_outch(sbuffer, buffer, currlen, maxlen, '.'); + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) + return 0; - while (fplace > 0) - doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]); + while (fplace > 0) { + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, + fconvert[--fplace])) + return 0; + } } while (zpadlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; --zpadlen; } while (padlen < 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; ++padlen; } + return 1; } -static void +#define BUFFER_INC 1024 + +static int doapr_outch( char **sbuffer, char **buffer, @@ -733,24 +766,30 @@ doapr_outch( /* If we haven't at least one buffer, someone has doe a big booboo */ assert(*sbuffer != NULL || buffer != NULL); - if (buffer) { - while (*currlen >= *maxlen) { - if (*buffer == NULL) { - if (*maxlen == 0) - *maxlen = 1024; + /* |currlen| must always be <= |*maxlen| */ + assert(*currlen <= *maxlen); + + if (buffer && *currlen == *maxlen) { + if (*maxlen > INT_MAX - BUFFER_INC) + return 0; + + *maxlen += BUFFER_INC; + if (*buffer == NULL) { *buffer = OPENSSL_malloc(*maxlen); + if (*buffer == NULL) + return 0; if (*currlen > 0) { assert(*sbuffer != NULL); memcpy(*buffer, *sbuffer, *currlen); } *sbuffer = NULL; - } else { - *maxlen += 1024; - *buffer = OPENSSL_realloc(*buffer, *maxlen); - } + } else { + char *tmpbuf; + tmpbuf = OPENSSL_realloc(*buffer, *maxlen); + if (tmpbuf == NULL) + return 0; + *buffer = tmpbuf; } - /* What to do if *buffer is NULL? */ - assert(*sbuffer != NULL || *buffer != NULL); } if (*currlen < *maxlen) { @@ -760,7 +799,7 @@ doapr_outch( (*buffer)[(*currlen)++] = (char)c; } - return; + return 1; } /***************************************************************************/ @@ -792,11 +831,15 @@ int BIO_vprintf (BIO *bio, const char *f dynbuf = NULL; CRYPTO_push_info("doapr()"); - _dopr(&hugebufp, &dynbuf, &hugebufsize, - &retlen, &ignored, format, args); + if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, + args)) + { + OPENSSL_free(dynbuf); + return -1; + } if (dynbuf) { - ret=BIO_write(bio, dynbuf, (int)retlen); + ret = BIO_write(bio, dynbuf, (int)retlen); OPENSSL_free(dynbuf); } else @@ -829,7 +872,8 @@ int BIO_vsnprintf(char *buf, size_t n, c size_t retlen; int truncated; - _dopr(&buf, NULL, &n, &retlen, &truncated, format, args); + if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) + return -1; if (truncated) /* In case of truncation, return -1 like traditional snprintf.