Skip to content

Commit 62b4eed

Browse files
authored
Handle string slices correctly in JS_ToCStringLen2 (#1184)
JS_ToCStringLen2 returns a pointer to a string that is prefixed by a JSString struct. It lets JS_FreeCString free the memory through simple pointer arithmetic. JS_ToCStringLen2 has an optimization for ASCII-only 8 bit strings where it returns early but that optimization is not valid for slice strings. They reference their string data indirectly and said data is not prefixed by a JSString. Fixes: #1178
1 parent 6446efc commit 62b4eed

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

api-test.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,23 @@ static void global_object_prototype(void)
631631
}
632632
}
633633

634+
// https://github.com/quickjs-ng/quickjs/issues/1178
635+
static void slice_string_tocstring(void)
636+
{
637+
JSRuntime *rt = JS_NewRuntime();
638+
JSContext *ctx = JS_NewContext(rt);
639+
static const char code[] = "'.'.repeat(16384).slice(1, -1)";
640+
JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
641+
assert(!JS_IsException(ret));
642+
assert(JS_IsString(ret));
643+
const char *str = JS_ToCString(ctx, ret);
644+
assert(strlen(str) == 16382);
645+
JS_FreeCString(ctx, str);
646+
JS_FreeValue(ctx, ret);
647+
JS_FreeContext(ctx);
648+
JS_FreeRuntime(rt);
649+
}
650+
634651
int main(void)
635652
{
636653
sync_call();
@@ -645,5 +662,6 @@ int main(void)
645662
dump_memory_usage();
646663
new_errors();
647664
global_object_prototype();
665+
slice_string_tocstring();
648666
return 0;
649667
}

quickjs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4277,7 +4277,7 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1,
42774277
for (pos = 0; pos < len; pos++) {
42784278
count += src[pos] >> 7;
42794279
}
4280-
if (count == 0) {
4280+
if (count == 0 && str->kind == JS_STRING_KIND_NORMAL) {
42814281
if (plen)
42824282
*plen = len;
42834283
return (const char *)src;

0 commit comments

Comments
 (0)