Skip to content

Commit 6ba35b0

Browse files
authored
Fix segfault in JS_NewSymbol with NULL description (#1447)
1 parent 3c05198 commit 6ba35b0

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

api-test.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,62 @@ static void get_uint8array(void)
962962
JS_FreeRuntime(rt);
963963
}
964964

965+
static void new_symbol(void)
966+
{
967+
JSRuntime *rt = JS_NewRuntime();
968+
JSContext *ctx = JS_NewContext(rt);
969+
JSValue global = JS_GetGlobalObject(ctx);
970+
JSValue sym, ret;
971+
972+
/* Local symbol with NULL description -> Symbol() */
973+
sym = JS_NewSymbol(ctx, NULL, false);
974+
assert(!JS_IsException(sym));
975+
assert(JS_IsSymbol(sym));
976+
JS_SetPropertyStr(ctx, global, "sym_local_null", sym);
977+
978+
ret = eval(ctx, "typeof sym_local_null === 'symbol' && sym_local_null.description === undefined && Symbol.keyFor(sym_local_null) === undefined");
979+
assert(JS_IsBool(ret));
980+
assert(JS_VALUE_GET_BOOL(ret));
981+
JS_FreeValue(ctx, ret);
982+
983+
/* Global symbol with NULL description -> Symbol.for() -> Symbol.for('undefined') */
984+
sym = JS_NewSymbol(ctx, NULL, true);
985+
assert(!JS_IsException(sym));
986+
assert(JS_IsSymbol(sym));
987+
JS_SetPropertyStr(ctx, global, "sym_global_null", sym);
988+
989+
ret = eval(ctx, "typeof sym_global_null === 'symbol' && sym_global_null.description === 'undefined' && Symbol.keyFor(sym_global_null) === 'undefined'");
990+
assert(JS_IsBool(ret));
991+
assert(JS_VALUE_GET_BOOL(ret));
992+
JS_FreeValue(ctx, ret);
993+
994+
/* Local symbol with description -> Symbol('test_local') */
995+
sym = JS_NewSymbol(ctx, "test_local", false);
996+
assert(!JS_IsException(sym));
997+
assert(JS_IsSymbol(sym));
998+
JS_SetPropertyStr(ctx, global, "sym_local_str", sym);
999+
1000+
ret = eval(ctx, "sym_local_str.description === 'test_local' && Symbol.keyFor(sym_local_str) === undefined");
1001+
assert(JS_IsBool(ret));
1002+
assert(JS_VALUE_GET_BOOL(ret));
1003+
JS_FreeValue(ctx, ret);
1004+
1005+
/* Global symbol with description -> Symbol.for('test_global') */
1006+
sym = JS_NewSymbol(ctx, "test_global", true);
1007+
assert(!JS_IsException(sym));
1008+
assert(JS_IsSymbol(sym));
1009+
JS_SetPropertyStr(ctx, global, "sym_global_str", sym);
1010+
1011+
ret = eval(ctx, "sym_global_str.description === 'test_global' && Symbol.keyFor(sym_global_str) === 'test_global'");
1012+
assert(JS_IsBool(ret));
1013+
assert(JS_VALUE_GET_BOOL(ret));
1014+
JS_FreeValue(ctx, ret);
1015+
1016+
JS_FreeValue(ctx, global);
1017+
JS_FreeContext(ctx);
1018+
JS_FreeRuntime(rt);
1019+
}
1020+
9651021
int main(void)
9661022
{
9671023
cfunctions();
@@ -981,5 +1037,6 @@ int main(void)
9811037
slice_string_tocstring();
9821038
immutable_array_buffer();
9831039
get_uint8array();
1040+
new_symbol();
9841041
return 0;
9851042
}

quickjs.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3404,6 +3404,15 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
34043404
/* `description` may be pure ASCII or UTF-8 encoded */
34053405
JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global)
34063406
{
3407+
if (description == NULL) {
3408+
if (!is_global) {
3409+
/* Local symbol without description: Symbol() */
3410+
return JS_NewSymbolInternal(ctx, NULL, JS_ATOM_TYPE_SYMBOL);
3411+
}
3412+
/* Global symbol without description: Symbol.for()
3413+
Per ES spec, ToString(undefined) becomes "undefined" */
3414+
description = "undefined";
3415+
}
34073416
JSAtom atom = JS_NewAtom(ctx, description);
34083417
if (atom == JS_ATOM_NULL)
34093418
return JS_EXCEPTION;

0 commit comments

Comments
 (0)