bug 599481 - static string tables should be constant. r=alangpierce

This commit is contained in:
Igor Bukanov 2010-09-25 00:36:58 +02:00
parent ac27a6ce80
commit bd21beac91
4 changed files with 55 additions and 20 deletions

View File

@ -3,15 +3,38 @@
*/
#include "tests.h"
#include "jsstr.h"
BEGIN_TEST(testIntString_bug515273)
{
jsvalRoot v(cx);
EVAL("'42';", v.addr());
EVAL("'1';", v.addr());
JSString *str = JSVAL_TO_STRING(v.value());
const char *bytes = JS_GetStringBytes(str);
CHECK(strcmp(bytes, "42") == 0);
CHECK(JSString::isStatic(str));
CHECK(strcmp(JS_GetStringBytes(str), "1") == 0);
EVAL("'42';", v.addr());
str = JSVAL_TO_STRING(v.value());
CHECK(JSString::isStatic(str));
CHECK(strcmp(JS_GetStringBytes(str), "42") == 0);
EVAL("'111';", v.addr());
str = JSVAL_TO_STRING(v.value());
CHECK(JSString::isStatic(str));
CHECK(strcmp(JS_GetStringBytes(str), "111") == 0);
/* Test other types of static strings. */
EVAL("'a';", v.addr());
str = JSVAL_TO_STRING(v.value());
CHECK(JSString::isStatic(str));
CHECK(strcmp(JS_GetStringBytes(str), "a") == 0);
EVAL("'bc';", v.addr());
str = JSVAL_TO_STRING(v.value());
CHECK(JSString::isStatic(str));
CHECK(strcmp(JS_GetStringBytes(str), "bc") == 0);
return true;
}
END_TEST(testIntString_bug515273)

View File

@ -3126,7 +3126,7 @@ static JSFunctionSpec string_methods[] = {
#pragma pack(push, 8)
#endif
JSString JSString::unitStringTable[]
const JSString JSString::unitStringTable[]
#ifdef __GNUC__
__attribute__ ((aligned (8)))
#endif
@ -3152,7 +3152,7 @@ __attribute__ ((aligned (8)))
#define R TO_SMALL_CHAR
JSString::SmallChar JSString::toSmallChar[] = { R7(0) };
const JSString::SmallChar JSString::toSmallChar[] = { R7(0) };
#undef R
@ -3165,7 +3165,7 @@ JSString::SmallChar JSString::toSmallChar[] = { R7(0) };
'A' - 36))
#define R FROM_SMALL_CHAR
jschar JSString::fromSmallChar[] = { R6(0) };
const jschar JSString::fromSmallChar[] = { R6(0) };
#undef R
@ -3186,7 +3186,7 @@ jschar JSString::fromSmallChar[] = { R6(0) };
#pragma pack(push, 8)
#endif
JSString JSString::length2StringTable[]
const JSString JSString::length2StringTable[]
#ifdef __GNUC__
__attribute__ ((aligned (8)))
#endif
@ -3228,7 +3228,7 @@ JS_STATIC_ASSERT(100 + (1 << 7) + (1 << 4) + (1 << 3) + (1 << 2) == 256);
#pragma pack(push, 8)
#endif
JSString JSString::hundredStringTable[]
const JSString JSString::hundredStringTable[]
#ifdef __GNUC__
__attribute__ ((aligned (8)))
#endif
@ -3246,7 +3246,7 @@ __attribute__ ((aligned (8)))
TO_SMALL_CHAR(((c) % 10) + '0') : \
JSString::hundredStringTable + ((c) - 100))
JSString *JSString::intStringTable[] = { R8(0) };
const JSString *const JSString::intStringTable[] = { R8(0) };
#undef R
@ -3491,7 +3491,7 @@ js_NewDependentString(JSContext *cx, JSString *base, size_t start,
jschar *chars = base->chars() + start;
if (length == 1 && *chars < UNIT_STRING_LIMIT)
return &JSString::unitStringTable[*chars];
return const_cast<JSString *>(&JSString::unitStringTable[*chars]);
/* Try to avoid long chains of dependent strings. */
while (base->isDependent())

View File

@ -276,6 +276,7 @@ struct JSString {
/* Specific flat string initializer and accessor methods. */
JS_ALWAYS_INLINE void initFlat(jschar *chars, size_t length) {
JS_ASSERT(length <= MAX_LENGTH);
JS_ASSERT(!isStatic(this));
e.mBase = NULL;
e.mCapacity = 0;
mLengthAndFlags = (length << FLAGS_LENGTH_SHIFT) | FLAT;
@ -284,6 +285,7 @@ struct JSString {
JS_ALWAYS_INLINE void initFlatMutable(jschar *chars, size_t length, size_t cap) {
JS_ASSERT(length <= MAX_LENGTH);
JS_ASSERT(!isStatic(this));
e.mBase = NULL;
e.mCapacity = cap;
mLengthAndFlags = (length << FLAGS_LENGTH_SHIFT) | FLAT | MUTABLE;
@ -334,6 +336,7 @@ struct JSString {
*/
inline void flatSetAtomized() {
JS_ASSERT(isFlat());
JS_ASSERT(!isStatic(this));
JS_ATOMIC_SET_MASK((jsword *)&mLengthAndFlags, ATOMIZED);
}
@ -345,6 +348,12 @@ struct JSString {
inline void flatClearMutable() {
JS_ASSERT(isFlat());
/*
* We cannot eliminate the flag check before writing to mLengthAndFlags as
* static strings may reside in write-protected memory. See bug 599481.
*/
if (mLengthAndFlags & MUTABLE)
mLengthAndFlags &= ~MUTABLE;
}
@ -354,6 +363,7 @@ struct JSString {
*/
inline void initDependent(JSString *bstr, jschar *chars, size_t len) {
JS_ASSERT(len <= MAX_LENGTH);
JS_ASSERT(!isStatic(this));
e.mParent = NULL;
mChars = chars;
mLengthAndFlags = DEPENDENT | (len << FLAGS_LENGTH_SHIFT);
@ -378,6 +388,7 @@ struct JSString {
inline void initTopNode(JSString *left, JSString *right, size_t len,
JSRopeBufferInfo *buf) {
JS_ASSERT(left->length() + right->length() <= MAX_LENGTH);
JS_ASSERT(!isStatic(this));
mLengthAndFlags = TOP_NODE | (len << FLAGS_LENGTH_SHIFT);
mLeft = left;
e.mRight = right;
@ -517,16 +528,16 @@ struct JSString {
static const SmallChar INVALID_SMALL_CHAR = -1;
static jschar fromSmallChar[];
static SmallChar toSmallChar[];
static JSString unitStringTable[];
static JSString length2StringTable[];
static JSString hundredStringTable[];
static const jschar fromSmallChar[];
static const SmallChar toSmallChar[];
static const JSString unitStringTable[];
static const JSString length2StringTable[];
static const JSString hundredStringTable[];
/*
* Since int strings can be unit strings, length-2 strings, or hundred
* strings, we keep a table to map from integer to the correct string.
*/
static JSString *intStringTable[];
static const JSString *const intStringTable[];
static const char deflatedIntStringTable[];
static const char deflatedUnitStringTable[];
static const char deflatedLength2StringTable[];

View File

@ -46,7 +46,7 @@ inline JSString *
JSString::unitString(jschar c)
{
JS_ASSERT(c < UNIT_STRING_LIMIT);
return &unitStringTable[c];
return const_cast<JSString *>(&unitStringTable[c]);
}
inline JSString *
@ -64,7 +64,8 @@ JSString::length2String(jschar c1, jschar c2)
{
JS_ASSERT(fitsInSmallChar(c1));
JS_ASSERT(fitsInSmallChar(c2));
return &length2StringTable[(((size_t)toSmallChar[c1]) << 6) + toSmallChar[c2]];
return const_cast<JSString *>
(&length2StringTable[(((size_t)toSmallChar[c1]) << 6) + toSmallChar[c2]]);
}
inline JSString *
@ -72,7 +73,7 @@ JSString::intString(jsint i)
{
jsuint u = jsuint(i);
JS_ASSERT(u < INT_STRING_LIMIT);
return JSString::intStringTable[u];
return const_cast<JSString *>(JSString::intStringTable[u]);
}
inline void