bug 528645 - js_IsAboutToBeFinalized must check for static strings. r=wagnerg

This commit is contained in:
Igor Bukanov 2009-12-22 23:50:44 +03:00
parent a9a607f1de
commit ea2c3a7d8a
4 changed files with 96 additions and 3 deletions

View File

@ -53,6 +53,7 @@ CPPSRCS = \
testDefineGetterSetterNonEnumerable.cpp \
testExtendedEq.cpp \
testIntString.cpp \
testIsAboutToBeFinalized.cpp \
testLookup.cpp \
testPropCache.cpp \
testTrap.cpp \

View File

@ -2,10 +2,10 @@
BEGIN_TEST(testIntString_bug515273)
{
jsval v;
EVAL("'42';", &v);
jsvalRoot v(cx);
EVAL("'42';", v.addr());
JSString *str = JSVAL_TO_STRING(v);
JSString *str = JSVAL_TO_STRING(v.value());
const char *bytes = JS_GetStringBytes(str);
CHECK(strcmp(bytes, "42") == 0);
return true;

View File

@ -0,0 +1,89 @@
#include "tests.h"
#include "jsstr.h"
static JSGCCallback oldGCCallback;
static void **checkPointers;
static jsuint checkPointersLength;
static JSBool
TestAboutToBeFinalizedCallback(JSContext *cx, JSGCStatus status)
{
if (status == JSGC_MARK_END && checkPointers) {
for (jsuint i = 0; i != checkPointersLength; ++i) {
void *p = checkPointers[i];
JS_ASSERT(p);
if (JS_IsAboutToBeFinalized(cx, p))
checkPointers[i] = NULL;
}
}
return !oldGCCallback || oldGCCallback(cx, status);
}
BEGIN_TEST(testIsAboutToBeFinalized_bug528645)
{
jsvalRoot root(cx);
/*
* Check various types of GC things against JS_IsAboutToBeFinalized.
* Make sure to include unit and numeric strings to the set.
*/
EVAL("var x = 1.1; "
"[x + 0.1, ''+x, 'a', '42', 'something'.substring(1), "
"{}, [], new Function('return 10;'), <xml/>];",
root.addr());
JSObject *array = JSVAL_TO_OBJECT(root.value());
JS_ASSERT(JS_IsArrayObject(cx, array));
JSBool ok = JS_GetArrayLength(cx, array, &checkPointersLength);
CHECK(ok);
void **elems = (void **) malloc(sizeof(void *) * checkPointersLength);
CHECK(elems);
size_t staticStrings = 0;
for (jsuint i = 0; i != checkPointersLength; ++i) {
jsval v;
ok = JS_GetElement(cx, array, i, &v);
CHECK(ok);
JS_ASSERT(JSVAL_IS_GCTHING(v));
JS_ASSERT(!JSVAL_IS_NULL(v));
elems[i] = JSVAL_TO_GCTHING(v);
if (JSString::isStatic(elems[i]))
++staticStrings;
}
oldGCCallback = JS_SetGCCallback(cx, TestAboutToBeFinalizedCallback);
checkPointers = elems;
JS_GC(cx);
/*
* All GC things are rooted via the root holding the array containing them
* and TestAboutToBeFinalizedCallback must keep them as is.
*/
for (jsuint i = 0; i != checkPointersLength; ++i)
CHECK(checkPointers[i]);
root = JSVAL_NULL;
JS_GC(cx);
/* Everything is unrooted except unit strings. */
for (jsuint i = 0; i != checkPointersLength; ++i) {
void *p = checkPointers[i];
if (p) {
CHECK(JSString::isStatic(p));
CHECK(staticStrings != 0);
--staticStrings;
}
}
CHECK(staticStrings == 0);
checkPointers = NULL;
JS_SetGCCallback(cx, oldGCCallback);
free(elems);
return true;
}
END_TEST(testIsAboutToBeFinalized_bug528645)

View File

@ -900,6 +900,9 @@ js_IsAboutToBeFinalized(void *thing)
JSGCArenaInfo *a;
uint32 index, flags;
if (JSString::isStatic(thing))
return false;
a = THING_TO_ARENA(thing);
if (!a->list) {
/*