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 "tests.h"
#include "jsstr.h"
BEGIN_TEST(testIntString_bug515273) BEGIN_TEST(testIntString_bug515273)
{ {
jsvalRoot v(cx); jsvalRoot v(cx);
EVAL("'42';", v.addr());
EVAL("'1';", v.addr());
JSString *str = JSVAL_TO_STRING(v.value()); JSString *str = JSVAL_TO_STRING(v.value());
const char *bytes = JS_GetStringBytes(str); CHECK(JSString::isStatic(str));
CHECK(strcmp(bytes, "42") == 0); 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; return true;
} }
END_TEST(testIntString_bug515273) END_TEST(testIntString_bug515273)

View File

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

View File

@ -276,6 +276,7 @@ struct JSString {
/* Specific flat string initializer and accessor methods. */ /* Specific flat string initializer and accessor methods. */
JS_ALWAYS_INLINE void initFlat(jschar *chars, size_t length) { JS_ALWAYS_INLINE void initFlat(jschar *chars, size_t length) {
JS_ASSERT(length <= MAX_LENGTH); JS_ASSERT(length <= MAX_LENGTH);
JS_ASSERT(!isStatic(this));
e.mBase = NULL; e.mBase = NULL;
e.mCapacity = 0; e.mCapacity = 0;
mLengthAndFlags = (length << FLAGS_LENGTH_SHIFT) | FLAT; 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_ALWAYS_INLINE void initFlatMutable(jschar *chars, size_t length, size_t cap) {
JS_ASSERT(length <= MAX_LENGTH); JS_ASSERT(length <= MAX_LENGTH);
JS_ASSERT(!isStatic(this));
e.mBase = NULL; e.mBase = NULL;
e.mCapacity = cap; e.mCapacity = cap;
mLengthAndFlags = (length << FLAGS_LENGTH_SHIFT) | FLAT | MUTABLE; mLengthAndFlags = (length << FLAGS_LENGTH_SHIFT) | FLAT | MUTABLE;
@ -334,6 +336,7 @@ struct JSString {
*/ */
inline void flatSetAtomized() { inline void flatSetAtomized() {
JS_ASSERT(isFlat()); JS_ASSERT(isFlat());
JS_ASSERT(!isStatic(this));
JS_ATOMIC_SET_MASK((jsword *)&mLengthAndFlags, ATOMIZED); JS_ATOMIC_SET_MASK((jsword *)&mLengthAndFlags, ATOMIZED);
} }
@ -345,7 +348,13 @@ struct JSString {
inline void flatClearMutable() { inline void flatClearMutable() {
JS_ASSERT(isFlat()); JS_ASSERT(isFlat());
mLengthAndFlags &= ~MUTABLE;
/*
* 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) { inline void initDependent(JSString *bstr, jschar *chars, size_t len) {
JS_ASSERT(len <= MAX_LENGTH); JS_ASSERT(len <= MAX_LENGTH);
JS_ASSERT(!isStatic(this));
e.mParent = NULL; e.mParent = NULL;
mChars = chars; mChars = chars;
mLengthAndFlags = DEPENDENT | (len << FLAGS_LENGTH_SHIFT); mLengthAndFlags = DEPENDENT | (len << FLAGS_LENGTH_SHIFT);
@ -378,6 +388,7 @@ struct JSString {
inline void initTopNode(JSString *left, JSString *right, size_t len, inline void initTopNode(JSString *left, JSString *right, size_t len,
JSRopeBufferInfo *buf) { JSRopeBufferInfo *buf) {
JS_ASSERT(left->length() + right->length() <= MAX_LENGTH); JS_ASSERT(left->length() + right->length() <= MAX_LENGTH);
JS_ASSERT(!isStatic(this));
mLengthAndFlags = TOP_NODE | (len << FLAGS_LENGTH_SHIFT); mLengthAndFlags = TOP_NODE | (len << FLAGS_LENGTH_SHIFT);
mLeft = left; mLeft = left;
e.mRight = right; e.mRight = right;
@ -517,16 +528,16 @@ struct JSString {
static const SmallChar INVALID_SMALL_CHAR = -1; static const SmallChar INVALID_SMALL_CHAR = -1;
static jschar fromSmallChar[]; static const jschar fromSmallChar[];
static SmallChar toSmallChar[]; static const SmallChar toSmallChar[];
static JSString unitStringTable[]; static const JSString unitStringTable[];
static JSString length2StringTable[]; static const JSString length2StringTable[];
static JSString hundredStringTable[]; static const JSString hundredStringTable[];
/* /*
* Since int strings can be unit strings, length-2 strings, or hundred * 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. * 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 deflatedIntStringTable[];
static const char deflatedUnitStringTable[]; static const char deflatedUnitStringTable[];
static const char deflatedLength2StringTable[]; static const char deflatedLength2StringTable[];

View File

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