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

This commit is contained in:
Jon Coppeard 2016-02-26 14:23:55 +00:00
Родитель cba834e152
Коммит cfa2e40539
1 изменённых файлов: 89 добавлений и 94 удалений

Просмотреть файл

@ -39,13 +39,16 @@ using namespace js;
#define VARARGS_ASSIGN(foo, bar) (foo) = (bar)
#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* cur;
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
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
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;
char chunk[CHUNK_SIZE];
@ -99,7 +102,7 @@ generic_write(PrintBuffer* buf, const char16_t* src, size_t srclen)
chunk[j++] = char(src[i++]);
if (j == CHUNK_SIZE || i == srclen) {
if (!buf->append(chunk, j))
if (!(*ss->stuff)(ss, chunk, j))
return false;
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
template <typename Char>
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 = ' ';
@ -119,18 +122,18 @@ fill2(PrintBuffer* buf, const Char* src, int srclen, int width, int flags)
if (flags & FLAG_ZEROS)
space = '0';
while (--width >= 0) {
if (!buf->append(&space, 1))
if (!(*ss->stuff)(ss, &space, 1))
return false;
}
}
// Copy out the source data
if (!generic_write(buf, src, srclen))
if (!generic_write(ss, src, srclen))
return false;
if (width > 0 && (flags & FLAG_LEFT) != 0) { // Left adjusting
while (--width >= 0) {
if (!buf->append(&space, 1))
if (!(*ss->stuff)(ss, &space, 1))
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
*/
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 precwidth = 0;
@ -191,32 +194,32 @@ fill_n(PrintBuffer* buf, const char* src, int srclen, int width, int prec, int t
}
}
while (--leftspaces >= 0) {
if (!buf->append(" ", 1))
if (!(*ss->stuff)(ss, " ", 1))
return false;
}
if (signwidth) {
if (!buf->append(&sign, 1))
if (!(*ss->stuff)(ss, &sign, 1))
return false;
}
while (--precwidth >= 0) {
if (!buf->append("0", 1))
if (!(*ss->stuff)(ss, "0", 1))
return false;
}
while (--zerowidth >= 0) {
if (!buf->append("0", 1))
if (!(*ss->stuff)(ss, "0", 1))
return false;
}
if (!buf->append(src, uint32_t(srclen)))
if (!(*ss->stuff)(ss, src, uint32_t(srclen)))
return false;
while (--rightspaces >= 0) {
if (!buf->append(" ", 1))
if (!(*ss->stuff)(ss, " ", 1))
return false;
}
return true;
}
/* 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)
{
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
// 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. */
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)
{
// 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
// 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
* 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 fout[300];
@ -311,7 +314,7 @@ static bool cvt_f(PrintBuffer* buf, double d, const char* fmt0, const char* fmt1
#endif
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)"; }
@ -327,7 +330,7 @@ static inline size_t generic_strlen(const char16_t* s) { return js_strlen(s); }
*/
template <typename Char>
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)
return true;
@ -340,7 +343,7 @@ cvt_s(PrintBuffer* buf, const Char* s, int width, int prec, int flags)
slen = prec;
// 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.
*/
static bool
dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
dosprintf(SprintfState* ss, const char* fmt, va_list ap)
{
char c;
int flags, width, prec, radix, type;
@ -601,7 +604,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
while ((c = *fmt++) != 0) {
if (c != '%') {
if (!buf->append(fmt - 1, 1))
if (!(*ss->stuff)(ss, fmt - 1, 1))
return false;
continue;
@ -614,7 +617,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
c = *fmt++;
if (c == '%') {
// quoting a % with %%
if (!buf->append(fmt - 1, 1))
if (!(*ss->stuff)(ss, fmt - 1, 1))
return false;
continue;
@ -763,7 +766,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case TYPE_UINT32:
u.l = (long)va_arg(ap, uint32_t);
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;
break;
@ -778,7 +781,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case TYPE_UINT64:
u.ll = va_arg(ap, uint64_t);
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;
break;
@ -795,11 +798,11 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
if (i < int(sizeof(pattern))) {
pattern[0] = '%';
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;
}
} else {
if (!cvt_f(buf, u.d, fmt0, fmt))
if (!cvt_f(ss, u.d, fmt0, fmt))
return false;
}
@ -808,7 +811,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case 'c':
if ((flags & FLAG_LEFT) == 0) {
while (width-- > 1) {
if (!buf->append(" ", 1))
if (!(*ss->stuff)(ss, " ", 1))
return false;
}
}
@ -816,13 +819,13 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case TYPE_INT16:
case TYPE_INTN:
u.ch = va_arg(ap, int);
if (!buf->append(&u.ch, 1))
if (!(*ss->stuff)(ss, &u.ch, 1))
return false;
break;
}
if (flags & FLAG_LEFT) {
while (width-- > 1) {
if (!buf->append(" ", 1))
if (!(*ss->stuff)(ss, " ", 1))
return false;
}
}
@ -855,11 +858,11 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case 's':
if(type == TYPE_INT16) {
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;
} else {
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;
}
break;
@ -867,7 +870,7 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
case 'n':
u.ip = va_arg(ap, int*);
if (u.ip) {
*u.ip = buf->cur - buf->base;
*u.ip = ss->cur - ss->base;
}
break;
@ -876,15 +879,15 @@ dosprintf(PrintBuffer* buf, const char* fmt, va_list ap)
#if 0
MOZ_ASSERT(0);
#endif
if (!buf->append("%", 1))
if (!(*ss->stuff)(ss, "%", 1))
return false;
if (!buf->append(fmt - 1, 1))
if (!(*ss->stuff)(ss, fmt - 1, 1))
return false;
}
}
// Stuff trailing NUL
if (!buf->append("\0", 1))
if (!(*ss->stuff)(ss, "\0", 1))
return false;
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.
*/
struct DynamicBuffer : public PrintBuffer
{
bool append(const char* sp, size_t len) override;
};
bool
DynamicBuffer::append(const char* sp, size_t len)
static bool
GrowStuff(SprintfState* ss, const char* sp, size_t len)
{
ptrdiff_t off;
char* newbase;
size_t newlen;
off = cur - base;
if (off + len >= maxlen) {
off = ss->cur - ss->base;
if (off + len >= ss->maxlen) {
/* Grow the buffer */
newlen = maxlen + ((len > 32) ? len : 32);
newbase = static_cast<char*>(js_realloc(base, newlen));
newlen = ss->maxlen + ((len > 32) ? len : 32);
newbase = static_cast<char*>(js_realloc(ss->base, newlen));
if (!newbase) {
/* Ran out of memory */
return false;
}
base = newbase;
maxlen = newlen;
cur = base + off;
ss->base = newbase;
ss->maxlen = newlen;
ss->cur = ss->base + off;
}
/* Copy data */
while (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;
}
@ -958,36 +956,32 @@ JS_smprintf_free(char* mem)
JS_PUBLIC_API(char*)
JS_vsmprintf(const char* fmt, va_list ap)
{
DynamicBuffer buf;
SprintfState ss;
buf.base = 0;
buf.cur = 0;
buf.maxlen = 0;
if (!dosprintf(&buf, fmt, ap)) {
js_free(buf.base);
ss.stuff = GrowStuff;
ss.base = 0;
ss.cur = 0;
ss.maxlen = 0;
if (!dosprintf(&ss, fmt, ap)) {
js_free(ss.base);
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;
};
bool
FixedBuffer::append(const char* sp, size_t len)
{
size_t limit = maxlen - (cur - base);
size_t limit = ss->maxlen - (ss->cur - ss->base);
if (len > limit)
len = limit;
while (len) {
--len;
*cur++ = *sp++;
*ss->cur++ = *sp++;
}
return true;
}
@ -1015,24 +1009,24 @@ JS_snprintf(char* out, uint32_t outlen, const char* fmt, ...)
JS_PUBLIC_API(uint32_t)
JS_vsnprintf(char* out, uint32_t outlen, const char* fmt, va_list ap)
{
FixedBuffer buf;
SprintfState ss;
if (outlen == 0)
return 0;
buf.base = out;
buf.cur = out;
buf.maxlen = outlen;
ss.stuff = LimitStuff;
ss.base = out;
ss.cur = out;
ss.maxlen = outlen;
(void) dosprintf(&ss, fmt, ap);
(void) dosprintf(&buf, fmt, ap);
uint32_t charsWritten = buf.cur - buf.base;
uint32_t charsWritten = ss.cur - ss.base;
MOZ_RELEASE_ASSERT(charsWritten > 0);
// 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.
if (buf.cur[-1] != '\0') {
buf.cur[-1] = '\0';
if (ss.cur[-1] != '\0') {
ss.cur[-1] = '\0';
return outlen;
}
@ -1056,23 +1050,24 @@ JS_sprintf_append(char* last, const char* fmt, ...)
JS_PUBLIC_API(char*)
JS_vsprintf_append(char* last, const char* fmt, va_list ap)
{
DynamicBuffer buf;
SprintfState ss;
ss.stuff = GrowStuff;
if (last) {
size_t lastlen = strlen(last);
buf.base = last;
buf.cur = last + lastlen;
buf.maxlen = lastlen;
ss.base = last;
ss.cur = last + lastlen;
ss.maxlen = lastlen;
} else {
buf.base = 0;
buf.cur = 0;
buf.maxlen = 0;
ss.base = 0;
ss.cur = 0;
ss.maxlen = 0;
}
if (!dosprintf(&buf, fmt, ap)) {
js_free(buf.base);
if (!dosprintf(&ss, fmt, ap)) {
js_free(ss.base);
return 0;
}
return buf.base;
return ss.base;
}
#undef TYPE_INT16