diff options
author | Wan-Teh Chang <wtc@google.com> | 2015-11-25 14:04:47 -0800 |
---|---|---|
committer | Wan-Teh Chang <wtc@google.com> | 2015-11-25 14:04:47 -0800 |
commit | 7892c25b0e59cbb1f4096fe36a0bf6f922688062 (patch) | |
tree | 19cd8ef0e65ffa479737289e98deaf538697ba82 | |
parent | 15844d34f3dc230cea44189dda4a461e3642993c (diff) | |
download | nspr-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.c | 32 |
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; |