Backed out changeset 94593f55cd01 (bug 1251303) for ASAN failures

This commit is contained in:
Jon Coppeard 2016-02-26 14:23:55 +00:00
parent d76a08e7f9
commit b44b7537c5

View File

@ -39,13 +39,16 @@ using namespace js;
#define VARARGS_ASSIGN(foo, bar) (foo) = (bar) #define VARARGS_ASSIGN(foo, bar) (foo) = (bar)
#endif #endif
struct PrintBuffer struct SprintfState
{ {
virtual bool append(const char* sp, size_t len) = 0; bool (*stuff)(SprintfState* ss, const char* sp, size_t len);
char* base; char* base;
char* cur; char* cur;
size_t maxlen; size_t maxlen;
int (*func)(void* arg, const char* sp, uint32_t len);
void* arg;
}; };
/* /*
@ -81,13 +84,13 @@ typedef mozilla::Vector<NumArgState, 20, js::SystemAllocPolicy> NumArgStateVecto
#define FLAG_NEG 0x10 #define FLAG_NEG 0x10
inline bool inline bool
generic_write(PrintBuffer* buf, const char* src, size_t srclen) generic_write(SprintfState* ss, const char* src, size_t srclen)
{ {
return buf->append(src, srclen); return (*ss->stuff)(ss, src, srclen);
} }
inline bool inline bool
generic_write(PrintBuffer* buf, const char16_t* src, size_t srclen) generic_write(SprintfState* ss, const char16_t* src, size_t srclen)
{ {
const size_t CHUNK_SIZE = 64; const size_t CHUNK_SIZE = 64;
char chunk[CHUNK_SIZE]; char chunk[CHUNK_SIZE];
@ -99,7 +102,7 @@ generic_write(PrintBuffer* buf, const char16_t* src, size_t srclen)
chunk[j++] = char(src[i++]); chunk[j++] = char(src[i++]);
if (j == CHUNK_SIZE || i == srclen) { if (j == CHUNK_SIZE || i == srclen) {
if (!buf->append(chunk, j)) if (!(*ss->stuff)(ss, chunk, j))
return false; return false;
j = 0; j = 0;
} }
@ -110,7 +113,7 @@ generic_write(PrintBuffer* buf, const char16_t* src, size_t srclen)
// Fill into the buffer using the data in src // Fill into the buffer using the data in src
template <typename Char> template <typename Char>
static bool static bool
fill2(PrintBuffer* buf, const Char* src, int srclen, int width, int flags) fill2(SprintfState* ss, const Char* src, int srclen, int width, int flags)
{ {
char space = ' '; char space = ' ';
@ -119,18 +122,18 @@ fill2(PrintBuffer* buf, const Char* src, int srclen, int width, int flags)
if (flags & FLAG_ZEROS) if (flags & FLAG_ZEROS)
space = '0'; space = '0';
while (--width >= 0) { while (--width >= 0) {
if (!buf->append(&space, 1)) if (!(*ss->stuff)(ss, &space, 1))
return false; return false;
} }
} }
// Copy out the source data // Copy out the source data
if (!generic_write(buf, src, srclen)) if (!generic_write(ss, src, srclen))
return false; return false;
if (width > 0 && (flags & FLAG_LEFT) != 0) { // Left adjusting if (width > 0 && (flags & FLAG_LEFT) != 0) { // Left adjusting
while (--width >= 0) { while (--width >= 0) {
if (!buf->append(&space, 1)) if (!(*ss->stuff)(ss, &space, 1))
return false; return false;
} }
} }
@ -141,7 +144,7 @@ fill2(PrintBuffer* buf, const Char* src, int srclen, int width, int flags)
* Fill a number. The order is: optional-sign zero-filling conversion-digits * Fill a number. The order is: optional-sign zero-filling conversion-digits
*/ */
static bool static bool
fill_n(PrintBuffer* buf, const char* src, int srclen, int width, int prec, int type, int flags) fill_n(SprintfState* ss, const char* src, int srclen, int width, int prec, int type, int flags)
{ {
int zerowidth = 0; int zerowidth = 0;
int precwidth = 0; int precwidth = 0;
@ -191,32 +194,32 @@ fill_n(PrintBuffer* buf, const char* src, int srclen, int width, int prec, int t
} }
} }
while (--leftspaces >= 0) { while (--leftspaces >= 0) {
if (!buf->append(" ", 1)) if (!(*ss->stuff)(ss, " ", 1))
return false; return false;
} }
if (signwidth) { if (signwidth) {
if (!buf->append(&sign, 1)) if (!(*ss->stuff)(ss, &sign, 1))
return false; return false;
} }
while (--precwidth >= 0) { while (--precwidth >= 0) {
if (!buf->append("0", 1)) if (!(*ss->stuff)(ss, "0", 1))
return false; return false;
} }
while (--zerowidth >= 0) { while (--zerowidth >= 0) {
if (!buf->append("0", 1)) if (!(*ss->stuff)(ss, "0", 1))
return false; return false;
} }
if (!buf->append(src, uint32_t(srclen))) if (!(*ss->stuff)(ss, src, uint32_t(srclen)))
return false; return false;
while (--rightspaces >= 0) { while (--rightspaces >= 0) {
if (!buf->append(" ", 1)) if (!(*ss->stuff)(ss, " ", 1))
return false; return false;
} }
return true; return true;
} }
/* Convert a long into its printable form. */ /* Convert a long into its printable form. */
static bool cvt_l(PrintBuffer* buf, long num, int width, int prec, int radix, static bool cvt_l(SprintfState* ss, long num, int width, int prec, int radix,
int type, int flags, const char* hexp) int type, int flags, const char* hexp)
{ {
char cvtbuf[100]; char cvtbuf[100];
@ -245,11 +248,11 @@ static bool cvt_l(PrintBuffer* buf, long num, int width, int prec, int radix,
// Now that we have the number converted without its sign, deal with // Now that we have the number converted without its sign, deal with
// the sign and zero padding. // the sign and zero padding.
return fill_n(buf, cvt, digits, width, prec, type, flags); return fill_n(ss, cvt, digits, width, prec, type, flags);
} }
/* Convert a 64-bit integer into its printable form. */ /* Convert a 64-bit integer into its printable form. */
static bool cvt_ll(PrintBuffer* buf, int64_t num, int width, int prec, int radix, static bool cvt_ll(SprintfState* ss, int64_t num, int width, int prec, int radix,
int type, int flags, const char* hexp) int type, int flags, const char* hexp)
{ {
// According to the man page, this needs to happen. // According to the man page, this needs to happen.
@ -278,14 +281,14 @@ static bool cvt_ll(PrintBuffer* buf, int64_t num, int width, int prec, int radix
// Now that we have the number converted without its sign, deal with // Now that we have the number converted without its sign, deal with
// the sign and zero padding. // the sign and zero padding.
return fill_n(buf, cvt, digits, width, prec, type, flags); return fill_n(ss, cvt, digits, width, prec, type, flags);
} }
/* /*
* Convert a double precision floating point number into its printable * Convert a double precision floating point number into its printable
* form. * form.
*/ */
static bool cvt_f(PrintBuffer* buf, double d, const char* fmt0, const char* fmt1) static bool cvt_f(SprintfState* ss, double d, const char* fmt0, const char* fmt1)
{ {
char fin[20]; char fin[20];
char fout[300]; char fout[300];
@ -311,7 +314,7 @@ static bool cvt_f(PrintBuffer* buf, double d, const char* fmt0, const char* fmt1
#endif #endif
snprintf_literal(fout, fin, d); snprintf_literal(fout, fin, d);
return buf->append(fout, strlen(fout)); return (*ss->stuff)(ss, fout, strlen(fout));
} }
static inline const char* generic_null_str(const char*) { return "(null)"; } static inline const char* generic_null_str(const char*) { return "(null)"; }
@ -327,7 +330,7 @@ static inline size_t generic_strlen(const char16_t* s) { return js_strlen(s); }
*/ */
template <typename Char> template <typename Char>
static bool static bool
cvt_s(PrintBuffer* buf, const Char* s, int width, int prec, int flags) cvt_s(SprintfState* ss, const Char* s, int width, int prec, int flags)
{ {
if (prec == 0) if (prec == 0)
return true; return true;
@ -340,7 +343,7 @@ cvt_s(PrintBuffer* buf, const Char* s, int width, int prec, int flags)
slen = prec; slen = prec;
// and away we go // and away we go
return fill2(buf, s, slen, width, flags); return fill2(ss, s, slen, width, flags);
} }
/* /*
@ -567,7 +570,7 @@ BuildArgArray(const char* fmt, va_list ap, NumArgStateVector& nas)
* The workhorse sprintf code. * The workhorse sprintf code.
*/ */
static bool static bool
dosprintf(PrintBuffer* buf, const char* fmt, va_list ap) dosprintf(SprintfState* ss, const char* fmt, va_list ap)
{ {
char c; char c;
int flags, width, prec, radix, type; int flags, width, prec, radix, type;
@ -601,7 +604,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
while ((c = *fmt++) != 0) { while ((c = *fmt++) != 0) {
if (c != '%') { if (c != '%') {
if (!buf->append(fmt - 1, 1)) if (!(*ss->stuff)(ss, fmt - 1, 1))
return false; return false;
continue; continue;
@ -614,7 +617,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
c = *fmt++; c = *fmt++;
if (c == '%') { if (c == '%') {
// quoting a % with %% // quoting a % with %%
if (!buf->append(fmt - 1, 1)) if (!(*ss->stuff)(ss, fmt - 1, 1))
return false; return false;
continue; continue;
@ -763,7 +766,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case TYPE_UINT32: case TYPE_UINT32:
u.l = (long)va_arg(ap, uint32_t); u.l = (long)va_arg(ap, uint32_t);
do_long: do_long:
if (!cvt_l(buf, u.l, width, prec, radix, type, flags, hexp)) if (!cvt_l(ss, u.l, width, prec, radix, type, flags, hexp))
return false; return false;
break; break;
@ -778,7 +781,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case TYPE_UINT64: case TYPE_UINT64:
u.ll = va_arg(ap, uint64_t); u.ll = va_arg(ap, uint64_t);
do_longlong: do_longlong:
if (!cvt_ll(buf, u.ll, width, prec, radix, type, flags, hexp)) if (!cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp))
return false; return false;
break; break;
@ -795,11 +798,11 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
if (i < int(sizeof(pattern))) { if (i < int(sizeof(pattern))) {
pattern[0] = '%'; pattern[0] = '%';
js_memcpy(&pattern[1], dolPt, size_t(i)); js_memcpy(&pattern[1], dolPt, size_t(i));
if (!cvt_f(buf, u.d, pattern, &pattern[i + 1])) if (!cvt_f(ss, u.d, pattern, &pattern[i + 1]))
return false; return false;
} }
} else { } else {
if (!cvt_f(buf, u.d, fmt0, fmt)) if (!cvt_f(ss, u.d, fmt0, fmt))
return false; return false;
} }
@ -808,7 +811,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case 'c': case 'c':
if ((flags & FLAG_LEFT) == 0) { if ((flags & FLAG_LEFT) == 0) {
while (width-- > 1) { while (width-- > 1) {
if (!buf->append(" ", 1)) if (!(*ss->stuff)(ss, " ", 1))
return false; return false;
} }
} }
@ -816,13 +819,13 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case TYPE_INT16: case TYPE_INT16:
case TYPE_INTN: case TYPE_INTN:
u.ch = va_arg(ap, int); u.ch = va_arg(ap, int);
if (!buf->append(&u.ch, 1)) if (!(*ss->stuff)(ss, &u.ch, 1))
return false; return false;
break; break;
} }
if (flags & FLAG_LEFT) { if (flags & FLAG_LEFT) {
while (width-- > 1) { while (width-- > 1) {
if (!buf->append(" ", 1)) if (!(*ss->stuff)(ss, " ", 1))
return false; return false;
} }
} }
@ -855,11 +858,11 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case 's': case 's':
if(type == TYPE_INT16) { if(type == TYPE_INT16) {
u.ws = va_arg(ap, const char16_t*); u.ws = va_arg(ap, const char16_t*);
if (!cvt_s(buf, u.ws, width, prec, flags)) if (!cvt_s(ss, u.ws, width, prec, flags))
return false; return false;
} else { } else {
u.s = va_arg(ap, const char*); u.s = va_arg(ap, const char*);
if (!cvt_s(buf, u.s, width, prec, flags)) if (!cvt_s(ss, u.s, width, prec, flags))
return false; return false;
} }
break; break;
@ -867,7 +870,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case 'n': case 'n':
u.ip = va_arg(ap, int*); u.ip = va_arg(ap, int*);
if (u.ip) { if (u.ip) {
*u.ip = buf->cur - buf->base; *u.ip = ss->cur - ss->base;
} }
break; break;
@ -876,15 +879,15 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
#if 0 #if 0
MOZ_ASSERT(0); MOZ_ASSERT(0);
#endif #endif
if (!buf->append("%", 1)) if (!(*ss->stuff)(ss, "%", 1))
return false; return false;
if (!buf->append(fmt - 1, 1)) if (!(*ss->stuff)(ss, fmt - 1, 1))
return false; return false;
} }
} }
// Stuff trailing NUL // Stuff trailing NUL
if (!buf->append("\0", 1)) if (!(*ss->stuff)(ss, "\0", 1))
return false; return false;
return true; return true;
@ -893,41 +896,36 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
/************************************************************************/ /************************************************************************/
/* /*
* Print buffer that automatically grows the js_malloc'd output buffer * Stuff routine that automatically grows the js_malloc'd output buffer
* before it overflows. * before it overflows.
*/ */
struct DynamicBuffer : public PrintBuffer static bool
{ GrowStuff(SprintfState* ss, const char* sp, size_t len)
bool append(const char* sp, size_t len) override;
};
bool
DynamicBuffer::append(const char* sp, size_t len)
{ {
ptrdiff_t off; ptrdiff_t off;
char* newbase; char* newbase;
size_t newlen; size_t newlen;
off = cur - base; off = ss->cur - ss->base;
if (off + len >= maxlen) { if (off + len >= ss->maxlen) {
/* Grow the buffer */ /* Grow the buffer */
newlen = maxlen + ((len > 32) ? len : 32); newlen = ss->maxlen + ((len > 32) ? len : 32);
newbase = static_cast<char*>(js_realloc(base, newlen)); newbase = static_cast<char*>(js_realloc(ss->base, newlen));
if (!newbase) { if (!newbase) {
/* Ran out of memory */ /* Ran out of memory */
return false; return false;
} }
base = newbase; ss->base = newbase;
maxlen = newlen; ss->maxlen = newlen;
cur = base + off; ss->cur = ss->base + off;
} }
/* Copy data */ /* Copy data */
while (len) { while (len) {
--len; --len;
*cur++ = *sp++; *ss->cur++ = *sp++;
} }
MOZ_ASSERT(size_t(cur - base) <= maxlen); MOZ_ASSERT(size_t(ss->cur - ss->base) <= ss->maxlen);
return true; return true;
} }
@ -958,36 +956,32 @@ JS_smprintf_free(char* mem)
JS_PUBLIC_API(char*) JS_PUBLIC_API(char*)
JS_vsmprintf(const char* fmt, va_list ap) JS_vsmprintf(const char* fmt, va_list ap)
{ {
DynamicBuffer buf; SprintfState ss;
buf.base = 0; ss.stuff = GrowStuff;
buf.cur = 0; ss.base = 0;
buf.maxlen = 0; ss.cur = 0;
if (!dosprintf(&buf, fmt, ap)) { ss.maxlen = 0;
js_free(buf.base); if (!dosprintf(&ss, fmt, ap)) {
js_free(ss.base);
return 0; return 0;
} }
return buf.base; return ss.base;
} }
/* /*
* Print buffer that discards overflow data * Stuff routine that discards overflow data
*/ */
struct FixedBuffer : public PrintBuffer static bool
LimitStuff(SprintfState* ss, const char* sp, size_t len)
{ {
bool append(const char* sp, size_t len) override; size_t limit = ss->maxlen - (ss->cur - ss->base);
};
bool
FixedBuffer::append(const char* sp, size_t len)
{
size_t limit = maxlen - (cur - base);
if (len > limit) if (len > limit)
len = limit; len = limit;
while (len) { while (len) {
--len; --len;
*cur++ = *sp++; *ss->cur++ = *sp++;
} }
return true; return true;
} }
@ -1015,24 +1009,24 @@ JS_snprintf(char* out, uint32_t outlen, const char* fmt, ...)
JS_PUBLIC_API(uint32_t) JS_PUBLIC_API(uint32_t)
JS_vsnprintf(char* out, uint32_t outlen, const char* fmt, va_list ap) JS_vsnprintf(char* out, uint32_t outlen, const char* fmt, va_list ap)
{ {
FixedBuffer buf; SprintfState ss;
if (outlen == 0) if (outlen == 0)
return 0; return 0;
buf.base = out; ss.stuff = LimitStuff;
buf.cur = out; ss.base = out;
buf.maxlen = outlen; ss.cur = out;
ss.maxlen = outlen;
(void) dosprintf(&ss, fmt, ap);
(void) dosprintf(&buf, fmt, ap); uint32_t charsWritten = ss.cur - ss.base;
uint32_t charsWritten = buf.cur - buf.base;
MOZ_RELEASE_ASSERT(charsWritten > 0); MOZ_RELEASE_ASSERT(charsWritten > 0);
// If we didn't append a null then we must have hit the buffer limit. Write // If we didn't append a null then we must have hit the buffer limit. Write
// a null terminator now and return a value indicating that we failed. // a null terminator now and return a value indicating that we failed.
if (buf.cur[-1] != '\0') { if (ss.cur[-1] != '\0') {
buf.cur[-1] = '\0'; ss.cur[-1] = '\0';
return outlen; return outlen;
} }
@ -1056,23 +1050,24 @@ JS_sprintf_append(char* last, const char* fmt, ...)
JS_PUBLIC_API(char*) JS_PUBLIC_API(char*)
JS_vsprintf_append(char* last, const char* fmt, va_list ap) JS_vsprintf_append(char* last, const char* fmt, va_list ap)
{ {
DynamicBuffer buf; SprintfState ss;
ss.stuff = GrowStuff;
if (last) { if (last) {
size_t lastlen = strlen(last); size_t lastlen = strlen(last);
buf.base = last; ss.base = last;
buf.cur = last + lastlen; ss.cur = last + lastlen;
buf.maxlen = lastlen; ss.maxlen = lastlen;
} else { } else {
buf.base = 0; ss.base = 0;
buf.cur = 0; ss.cur = 0;
buf.maxlen = 0; ss.maxlen = 0;
} }
if (!dosprintf(&buf, fmt, ap)) { if (!dosprintf(&ss, fmt, ap)) {
js_free(buf.base); js_free(ss.base);
return 0; return 0;
} }
return buf.base; return ss.base;
} }
#undef TYPE_INT16 #undef TYPE_INT16