Skip to content

Commit 73be8a5

Browse files
authored
Store start of slice string as bytes, not chars (#1186)
Not all functions access the string's backing memory according to the string's encoding. js_regexp_match in particular uses str8 for both ascii and wide strings. Because the offset into the parent string was stored in characters, js_regexp_match used the wrong offset (off by 50%) for wide slice strings. It's conceivable other functions do something similarly ill-advised, so store the start in bytes instead of characters from now on. Fixes: #1178
1 parent 62b4eed commit 73be8a5

File tree

1 file changed

+11
-16
lines changed

1 file changed

+11
-16
lines changed

quickjs.c

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -580,10 +580,10 @@ struct JSString {
580580

581581
typedef struct JSStringSlice {
582582
JSString *parent;
583-
uint32_t start; // in characters, not bytes
583+
uint32_t start; // in bytes, not characters
584584
} JSStringSlice;
585585

586-
static inline uint8_t *str8(JSString *p)
586+
static inline void *strv(JSString *p)
587587
{
588588
JSStringSlice *slice;
589589

@@ -592,25 +592,20 @@ static inline uint8_t *str8(JSString *p)
592592
return (void *)&p[1];
593593
case JS_STRING_KIND_SLICE:
594594
slice = (void *)&p[1];
595-
return str8(slice->parent) + slice->start;
595+
return (char *)&slice->parent[1] + slice->start;
596596
}
597597
abort();
598598
return NULL;
599599
}
600600

601-
static inline uint16_t *str16(JSString *p)
601+
static inline uint8_t *str8(JSString *p)
602602
{
603-
JSStringSlice *slice;
603+
return strv(p);
604+
}
604605

605-
switch (p->kind) {
606-
case JS_STRING_KIND_NORMAL:
607-
return (void *)&p[1];
608-
case JS_STRING_KIND_SLICE:
609-
slice = (void *)&p[1];
610-
return str16(slice->parent) + slice->start;
611-
}
612-
abort();
613-
return NULL;
606+
static inline uint16_t *str16(JSString *p)
607+
{
608+
return strv(p);
614609
}
615610

616611
typedef struct JSClosureVar {
@@ -3750,7 +3745,7 @@ static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end)
37503745
if (p->kind == JS_STRING_KIND_SLICE) {
37513746
slice = (void *)&p[1];
37523747
p = slice->parent;
3753-
start += slice->start;
3748+
start += slice->start >> p->is_wide_char; // bytes -> chars
37543749
}
37553750
// allocate as 16 bit wide string to avoid wastage;
37563751
// js_alloc_string allocates 1 byte extra for 8 bit strings;
@@ -3762,7 +3757,7 @@ static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end)
37623757
q->len = len;
37633758
slice = (void *)&q[1];
37643759
slice->parent = p;
3765-
slice->start = start;
3760+
slice->start = start << p->is_wide_char; // chars -> bytes
37663761
p->header.ref_count++;
37673762
return JS_MKPTR(JS_TAG_STRING, q);
37683763
}

0 commit comments

Comments
 (0)