Skip to content

Commit 708dbcb

Browse files
authored
Fix big endian serialization (#269)
* Fix big endian serialization Big endian serialization was broken because: - it partially relied on `WORDS_ENDIAN` (unconditionally undef'd in cutils.h) - endianness was not handled at all in the bc reader. - `bc_tag_str` was missing the `"RegExp"` string - `lre_byte_swap()` was broken for `REOP_range` and `REOP_range32` Modifications: - remove `WORDS_ENDIAN` - use `bc_put_u32()` / `bc_put_u64()` in `JS_WriteBigInt()` - use `bc_get_u32()` / `bc_get_u64()` in `JS_ReadBigInt()` - handle host endianness in `bc_get_u16()`, `bc_get_u32()`, `bc_get_u64()` and `JS_ReadFunctionBytecode()` - handle optional littleEndian argument as specified in `js_dataview_getValue()` and `js_dataview_setValue()` - fix `bc_tag_str` and `lre_byte_swap()`
1 parent f406d6f commit 708dbcb

File tree

3 files changed

+40
-38
lines changed

3 files changed

+40
-38
lines changed

cutils.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@
2929
#include <string.h>
3030
#include <inttypes.h>
3131

32-
/* set if CPU is big endian */
33-
#undef WORDS_BIGENDIAN
34-
3532
#if defined(_MSC_VER)
3633
#include <windows.h>
3734
#include <winsock2.h>

libregexp.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2598,7 +2598,7 @@ const char *lre_get_groupnames(const uint8_t *bc_buf)
25982598
void lre_byte_swap(uint8_t *buf, size_t len, BOOL is_byte_swapped)
25992599
{
26002600
uint8_t *p, *pe;
2601-
uint32_t n, r;
2601+
uint32_t n, r, nw;
26022602

26032603
p = buf;
26042604
if (len < RE_HEADER_LEN)
@@ -2633,16 +2633,23 @@ void lre_byte_swap(uint8_t *buf, size_t len, BOOL is_byte_swapped)
26332633
case REOP_save_reset: // has two 8 bit arguments
26342634
break;
26352635
case REOP_range32: // variable length
2636-
for (r = 3 + 4 * get_u16(&p[1]); n < r; n += 4)
2636+
nw = get_u16(&p[1]); // number of pairs of uint32_t
2637+
if (is_byte_swapped)
2638+
n = bswap16(n);
2639+
for (r = 3 + 8 * nw; n < r; n += 4)
26372640
inplace_bswap32(&p[n]);
26382641
goto doswap16;
26392642
case REOP_range: // variable length
2640-
for (r = 3 + 2 * get_u16(&p[1]); n < r; n += 2)
2643+
nw = get_u16(&p[1]); // number of pairs of uint16_t
2644+
if (is_byte_swapped)
2645+
n = bswap16(n);
2646+
for (r = 3 + 4 * nw; n < r; n += 2)
26412647
inplace_bswap16(&p[n]);
26422648
goto doswap16;
26432649
default:
26442650
doswap16:
26452651
inplace_bswap16(&p[1]);
2652+
break;
26462653
}
26472654
break;
26482655
case 5:

quickjs.c

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -32325,6 +32325,7 @@ static const char * const bc_tag_str[] = {
3232532325
"TypedArray",
3232632326
"ArrayBuffer",
3232732327
"SharedArrayBuffer",
32328+
"RegExp",
3232832329
"Date",
3232932330
"ObjectValue",
3233032331
"ObjectReference",
@@ -32613,20 +32614,14 @@ static int JS_WriteBigInt(BCWriterState *s, JSValue obj)
3261332614
bc_put_leb128(s, len);
3261432615
/* always saved in byte based little endian representation */
3261532616
for(j = 0; j < n1; j++) {
32616-
dbuf_putc(&s->dbuf, v >> (j * 8));
32617+
bc_put_u8(s, v >> (j * 8));
3261732618
}
3261832619
for(; i < a->len; i++) {
3261932620
limb_t v = a->tab[i];
3262032621
#if LIMB_BITS == 32
32621-
#ifdef WORDS_BIGENDIAN
32622-
v = bswap32(v);
32623-
#endif
32624-
dbuf_put_u32(&s->dbuf, v);
32622+
bc_put_u32(s, v);
3262532623
#else
32626-
#ifdef WORDS_BIGENDIAN
32627-
v = bswap64(v);
32628-
#endif
32629-
dbuf_put_u64(&s->dbuf, v);
32624+
bc_put_u64(s, v);
3263032625
#endif
3263132626
}
3263232627
}
@@ -33218,33 +33213,45 @@ static int bc_get_u8(BCReaderState *s, uint8_t *pval)
3321833213

3321933214
static int bc_get_u16(BCReaderState *s, uint16_t *pval)
3322033215
{
33216+
uint16_t v;
3322133217
if (unlikely(s->buf_end - s->ptr < 2)) {
3322233218
*pval = 0; /* avoid warning */
3322333219
return bc_read_error_end(s);
3322433220
}
33225-
*pval = get_u16(s->ptr);
33221+
v = get_u16(s->ptr);
33222+
if (is_be())
33223+
v = bswap16(v);
33224+
*pval = v;
3322633225
s->ptr += 2;
3322733226
return 0;
3322833227
}
3322933228

3323033229
static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
3323133230
{
33231+
uint32_t v;
3323233232
if (unlikely(s->buf_end - s->ptr < 4)) {
3323333233
*pval = 0; /* avoid warning */
3323433234
return bc_read_error_end(s);
3323533235
}
33236-
*pval = get_u32(s->ptr);
33236+
v = get_u32(s->ptr);
33237+
if (is_be())
33238+
v = bswap32(v);
33239+
*pval = v;
3323733240
s->ptr += 4;
3323833241
return 0;
3323933242
}
3324033243

3324133244
static int bc_get_u64(BCReaderState *s, uint64_t *pval)
3324233245
{
33246+
uint64_t v;
3324333247
if (unlikely(s->buf_end - s->ptr < 8)) {
3324433248
*pval = 0; /* avoid warning */
3324533249
return bc_read_error_end(s);
3324633250
}
33247-
*pval = get_u64(s->ptr);
33251+
v = get_u64(s->ptr);
33252+
if (is_be())
33253+
v = bswap64(v);
33254+
*pval = v;
3324833255
s->ptr += 8;
3324933256
return 0;
3325033257
}
@@ -33387,6 +33394,9 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,
3338733394
return -1;
3338833395
b->byte_code_buf = bc_buf;
3338933396

33397+
if (is_be())
33398+
bc_byte_swap(bc_buf, bc_len);
33399+
3339033400
pos = 0;
3339133401
while (pos < bc_len) {
3339233402
op = bc_buf[pos];
@@ -33481,15 +33491,9 @@ static JSValue JS_ReadBigInt(BCReaderState *s)
3348133491
#if LIMB_BITS == 32
3348233492
if (bc_get_u32(s, &v))
3348333493
goto fail;
33484-
#ifdef WORDS_BIGENDIAN
33485-
v = bswap32(v);
33486-
#endif
3348733494
#else
3348833495
if (bc_get_u64(s, &v))
3348933496
goto fail;
33490-
#ifdef WORDS_BIGENDIAN
33491-
v = bswap64(v);
33492-
#endif
3349333497
#endif
3349433498
a->tab[i] = v;
3349533499
}
@@ -50561,7 +50565,8 @@ static JSValue js_dataview_getValue(JSContext *ctx,
5056150565
{
5056250566
JSTypedArray *ta;
5056350567
JSArrayBuffer *abuf;
50564-
int is_swap, size;
50568+
BOOL littleEndian, is_swap;
50569+
int size;
5056550570
uint8_t *ptr;
5056650571
uint32_t v;
5056750572
uint64_t pos;
@@ -50572,12 +50577,8 @@ static JSValue js_dataview_getValue(JSContext *ctx,
5057250577
size = 1 << typed_array_size_log2(class_id);
5057350578
if (JS_ToIndex(ctx, &pos, argv[0]))
5057450579
return JS_EXCEPTION;
50575-
is_swap = FALSE;
50576-
if (argc > 1)
50577-
is_swap = JS_ToBool(ctx, argv[1]);
50578-
#ifndef WORDS_BIGENDIAN
50579-
is_swap ^= 1;
50580-
#endif
50580+
littleEndian = argc > 1 && JS_ToBool(ctx, argv[1]);
50581+
is_swap = littleEndian ^ !is_be();
5058150582
abuf = ta->buffer->u.array_buffer;
5058250583
if (abuf->detached)
5058350584
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
@@ -50663,7 +50664,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
5066350664
{
5066450665
JSTypedArray *ta;
5066550666
JSArrayBuffer *abuf;
50666-
int is_swap, size;
50667+
BOOL littleEndian, is_swap;
50668+
int size;
5066750669
uint8_t *ptr;
5066850670
uint64_t v64;
5066950671
uint32_t v;
@@ -50703,12 +50705,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
5070350705
v64 = u.u64;
5070450706
}
5070550707
}
50706-
is_swap = FALSE;
50707-
if (argc > 2)
50708-
is_swap = JS_ToBool(ctx, argv[2]);
50709-
#ifndef WORDS_BIGENDIAN
50710-
is_swap ^= 1;
50711-
#endif
50708+
littleEndian = argc > 2 && JS_ToBool(ctx, argv[2]);
50709+
is_swap = littleEndian ^ !is_be();
5071250710
abuf = ta->buffer->u.array_buffer;
5071350711
if (abuf->detached)
5071450712
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);

0 commit comments

Comments
 (0)