summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWan-Teh Chang <wtc@google.com>2015-11-25 14:04:47 -0800
committerWan-Teh Chang <wtc@google.com>2015-11-25 14:04:47 -0800
commit7892c25b0e59cbb1f4096fe36a0bf6f922688062 (patch)
tree19cd8ef0e65ffa479737289e98deaf538697ba82
parent15844d34f3dc230cea44189dda4a461e3642993c (diff)
downloadnspr-hg-7892c25b0e59cbb1f4096fe36a0bf6f922688062.tar.gz
Bug 1174015: Keep the maxlen member of SprintfState under PR_INT32_MAX.
r=kaie.
-rw-r--r--pr/src/io/prprf.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/pr/src/io/prprf.c b/pr/src/io/prprf.c
index 1a891415..e7c35cfb 100644
--- a/pr/src/io/prprf.c
+++ b/pr/src/io/prprf.c
@@ -37,7 +37,7 @@ struct SprintfStateStr {
char *base;
char *cur;
- PRUint32 maxlen;
+ PRUint32 maxlen; /* Must not exceed PR_INT32_MAX. */
int (*func)(void *arg, const char *sp, PRUint32 len);
void *arg;
@@ -1060,6 +1060,13 @@ static int FuncStuff(SprintfState *ss, const char *sp, PRUint32 len)
{
int rv;
+ /*
+ ** We will add len to ss->maxlen at the end of the function. First check
+ ** if ss->maxlen + len would overflow or be greater than PR_INT32_MAX.
+ */
+ if (PR_UINT32_MAX - ss->maxlen < len || ss->maxlen + len > PR_INT32_MAX) {
+ return -1;
+ }
rv = (*ss->func)(ss->arg, sp, len);
if (rv < 0) {
return rv;
@@ -1105,9 +1112,21 @@ static int GrowStuff(SprintfState *ss, const char *sp, PRUint32 len)
PRUint32 newlen;
off = ss->cur - ss->base;
+ if (PR_UINT32_MAX - len < off) {
+ /* off + len would be too big. */
+ return -1;
+ }
if (off + len >= ss->maxlen) {
/* Grow the buffer */
- newlen = ss->maxlen + ((len > 32) ? len : 32);
+ PRUint32 increment = (len > 32) ? len : 32;
+ if (PR_UINT32_MAX - ss->maxlen < increment) {
+ /* ss->maxlen + increment would overflow. */
+ return -1;
+ }
+ newlen = ss->maxlen + increment;
+ if (newlen > PR_INT32_MAX) {
+ return -1;
+ }
if (ss->base) {
newbase = (char*) PR_REALLOC(ss->base, newlen);
} else {
@@ -1210,8 +1229,8 @@ PR_IMPLEMENT(PRUint32) PR_vsnprintf(char *out, PRUint32 outlen,const char *fmt,
SprintfState ss;
PRUint32 n;
- PR_ASSERT((PRInt32)outlen > 0);
- if ((PRInt32)outlen <= 0) {
+ PR_ASSERT(outlen != 0 && outlen <= PR_INT32_MAX);
+ if (outlen == 0 || outlen > PR_INT32_MAX) {
return 0;
}
@@ -1247,7 +1266,10 @@ PR_IMPLEMENT(char *) PR_vsprintf_append(char *last, const char *fmt, va_list ap)
ss.stuff = GrowStuff;
if (last) {
- int lastlen = strlen(last);
+ size_t lastlen = strlen(last);
+ if (lastlen > PR_INT32_MAX) {
+ return 0;
+ }
ss.base = last;
ss.cur = last + lastlen;
ss.maxlen = lastlen;