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()`
This commit is contained in:
parent
f406d6f78c
commit
708dbcbf5b
3 changed files with 40 additions and 38 deletions
3
cutils.h
3
cutils.h
|
@ -29,9 +29,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
/* set if CPU is big endian */
|
|
||||||
#undef WORDS_BIGENDIAN
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
|
13
libregexp.c
13
libregexp.c
|
@ -2598,7 +2598,7 @@ const char *lre_get_groupnames(const uint8_t *bc_buf)
|
||||||
void lre_byte_swap(uint8_t *buf, size_t len, BOOL is_byte_swapped)
|
void lre_byte_swap(uint8_t *buf, size_t len, BOOL is_byte_swapped)
|
||||||
{
|
{
|
||||||
uint8_t *p, *pe;
|
uint8_t *p, *pe;
|
||||||
uint32_t n, r;
|
uint32_t n, r, nw;
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
if (len < RE_HEADER_LEN)
|
if (len < RE_HEADER_LEN)
|
||||||
|
@ -2633,16 +2633,23 @@ void lre_byte_swap(uint8_t *buf, size_t len, BOOL is_byte_swapped)
|
||||||
case REOP_save_reset: // has two 8 bit arguments
|
case REOP_save_reset: // has two 8 bit arguments
|
||||||
break;
|
break;
|
||||||
case REOP_range32: // variable length
|
case REOP_range32: // variable length
|
||||||
for (r = 3 + 4 * get_u16(&p[1]); n < r; n += 4)
|
nw = get_u16(&p[1]); // number of pairs of uint32_t
|
||||||
|
if (is_byte_swapped)
|
||||||
|
n = bswap16(n);
|
||||||
|
for (r = 3 + 8 * nw; n < r; n += 4)
|
||||||
inplace_bswap32(&p[n]);
|
inplace_bswap32(&p[n]);
|
||||||
goto doswap16;
|
goto doswap16;
|
||||||
case REOP_range: // variable length
|
case REOP_range: // variable length
|
||||||
for (r = 3 + 2 * get_u16(&p[1]); n < r; n += 2)
|
nw = get_u16(&p[1]); // number of pairs of uint16_t
|
||||||
|
if (is_byte_swapped)
|
||||||
|
n = bswap16(n);
|
||||||
|
for (r = 3 + 4 * nw; n < r; n += 2)
|
||||||
inplace_bswap16(&p[n]);
|
inplace_bswap16(&p[n]);
|
||||||
goto doswap16;
|
goto doswap16;
|
||||||
default:
|
default:
|
||||||
doswap16:
|
doswap16:
|
||||||
inplace_bswap16(&p[1]);
|
inplace_bswap16(&p[1]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
|
|
62
quickjs.c
62
quickjs.c
|
@ -32325,6 +32325,7 @@ static const char * const bc_tag_str[] = {
|
||||||
"TypedArray",
|
"TypedArray",
|
||||||
"ArrayBuffer",
|
"ArrayBuffer",
|
||||||
"SharedArrayBuffer",
|
"SharedArrayBuffer",
|
||||||
|
"RegExp",
|
||||||
"Date",
|
"Date",
|
||||||
"ObjectValue",
|
"ObjectValue",
|
||||||
"ObjectReference",
|
"ObjectReference",
|
||||||
|
@ -32613,20 +32614,14 @@ static int JS_WriteBigInt(BCWriterState *s, JSValue obj)
|
||||||
bc_put_leb128(s, len);
|
bc_put_leb128(s, len);
|
||||||
/* always saved in byte based little endian representation */
|
/* always saved in byte based little endian representation */
|
||||||
for(j = 0; j < n1; j++) {
|
for(j = 0; j < n1; j++) {
|
||||||
dbuf_putc(&s->dbuf, v >> (j * 8));
|
bc_put_u8(s, v >> (j * 8));
|
||||||
}
|
}
|
||||||
for(; i < a->len; i++) {
|
for(; i < a->len; i++) {
|
||||||
limb_t v = a->tab[i];
|
limb_t v = a->tab[i];
|
||||||
#if LIMB_BITS == 32
|
#if LIMB_BITS == 32
|
||||||
#ifdef WORDS_BIGENDIAN
|
bc_put_u32(s, v);
|
||||||
v = bswap32(v);
|
|
||||||
#endif
|
|
||||||
dbuf_put_u32(&s->dbuf, v);
|
|
||||||
#else
|
#else
|
||||||
#ifdef WORDS_BIGENDIAN
|
bc_put_u64(s, v);
|
||||||
v = bswap64(v);
|
|
||||||
#endif
|
|
||||||
dbuf_put_u64(&s->dbuf, v);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33218,33 +33213,45 @@ static int bc_get_u8(BCReaderState *s, uint8_t *pval)
|
||||||
|
|
||||||
static int bc_get_u16(BCReaderState *s, uint16_t *pval)
|
static int bc_get_u16(BCReaderState *s, uint16_t *pval)
|
||||||
{
|
{
|
||||||
|
uint16_t v;
|
||||||
if (unlikely(s->buf_end - s->ptr < 2)) {
|
if (unlikely(s->buf_end - s->ptr < 2)) {
|
||||||
*pval = 0; /* avoid warning */
|
*pval = 0; /* avoid warning */
|
||||||
return bc_read_error_end(s);
|
return bc_read_error_end(s);
|
||||||
}
|
}
|
||||||
*pval = get_u16(s->ptr);
|
v = get_u16(s->ptr);
|
||||||
|
if (is_be())
|
||||||
|
v = bswap16(v);
|
||||||
|
*pval = v;
|
||||||
s->ptr += 2;
|
s->ptr += 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
|
static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
|
||||||
{
|
{
|
||||||
|
uint32_t v;
|
||||||
if (unlikely(s->buf_end - s->ptr < 4)) {
|
if (unlikely(s->buf_end - s->ptr < 4)) {
|
||||||
*pval = 0; /* avoid warning */
|
*pval = 0; /* avoid warning */
|
||||||
return bc_read_error_end(s);
|
return bc_read_error_end(s);
|
||||||
}
|
}
|
||||||
*pval = get_u32(s->ptr);
|
v = get_u32(s->ptr);
|
||||||
|
if (is_be())
|
||||||
|
v = bswap32(v);
|
||||||
|
*pval = v;
|
||||||
s->ptr += 4;
|
s->ptr += 4;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bc_get_u64(BCReaderState *s, uint64_t *pval)
|
static int bc_get_u64(BCReaderState *s, uint64_t *pval)
|
||||||
{
|
{
|
||||||
|
uint64_t v;
|
||||||
if (unlikely(s->buf_end - s->ptr < 8)) {
|
if (unlikely(s->buf_end - s->ptr < 8)) {
|
||||||
*pval = 0; /* avoid warning */
|
*pval = 0; /* avoid warning */
|
||||||
return bc_read_error_end(s);
|
return bc_read_error_end(s);
|
||||||
}
|
}
|
||||||
*pval = get_u64(s->ptr);
|
v = get_u64(s->ptr);
|
||||||
|
if (is_be())
|
||||||
|
v = bswap64(v);
|
||||||
|
*pval = v;
|
||||||
s->ptr += 8;
|
s->ptr += 8;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -33387,6 +33394,9 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,
|
||||||
return -1;
|
return -1;
|
||||||
b->byte_code_buf = bc_buf;
|
b->byte_code_buf = bc_buf;
|
||||||
|
|
||||||
|
if (is_be())
|
||||||
|
bc_byte_swap(bc_buf, bc_len);
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (pos < bc_len) {
|
while (pos < bc_len) {
|
||||||
op = bc_buf[pos];
|
op = bc_buf[pos];
|
||||||
|
@ -33481,15 +33491,9 @@ static JSValue JS_ReadBigInt(BCReaderState *s)
|
||||||
#if LIMB_BITS == 32
|
#if LIMB_BITS == 32
|
||||||
if (bc_get_u32(s, &v))
|
if (bc_get_u32(s, &v))
|
||||||
goto fail;
|
goto fail;
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
v = bswap32(v);
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
if (bc_get_u64(s, &v))
|
if (bc_get_u64(s, &v))
|
||||||
goto fail;
|
goto fail;
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
v = bswap64(v);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
a->tab[i] = v;
|
a->tab[i] = v;
|
||||||
}
|
}
|
||||||
|
@ -50561,7 +50565,8 @@ static JSValue js_dataview_getValue(JSContext *ctx,
|
||||||
{
|
{
|
||||||
JSTypedArray *ta;
|
JSTypedArray *ta;
|
||||||
JSArrayBuffer *abuf;
|
JSArrayBuffer *abuf;
|
||||||
int is_swap, size;
|
BOOL littleEndian, is_swap;
|
||||||
|
int size;
|
||||||
uint8_t *ptr;
|
uint8_t *ptr;
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
uint64_t pos;
|
uint64_t pos;
|
||||||
|
@ -50572,12 +50577,8 @@ static JSValue js_dataview_getValue(JSContext *ctx,
|
||||||
size = 1 << typed_array_size_log2(class_id);
|
size = 1 << typed_array_size_log2(class_id);
|
||||||
if (JS_ToIndex(ctx, &pos, argv[0]))
|
if (JS_ToIndex(ctx, &pos, argv[0]))
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
is_swap = FALSE;
|
littleEndian = argc > 1 && JS_ToBool(ctx, argv[1]);
|
||||||
if (argc > 1)
|
is_swap = littleEndian ^ !is_be();
|
||||||
is_swap = JS_ToBool(ctx, argv[1]);
|
|
||||||
#ifndef WORDS_BIGENDIAN
|
|
||||||
is_swap ^= 1;
|
|
||||||
#endif
|
|
||||||
abuf = ta->buffer->u.array_buffer;
|
abuf = ta->buffer->u.array_buffer;
|
||||||
if (abuf->detached)
|
if (abuf->detached)
|
||||||
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
|
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
|
||||||
|
@ -50663,7 +50664,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
|
||||||
{
|
{
|
||||||
JSTypedArray *ta;
|
JSTypedArray *ta;
|
||||||
JSArrayBuffer *abuf;
|
JSArrayBuffer *abuf;
|
||||||
int is_swap, size;
|
BOOL littleEndian, is_swap;
|
||||||
|
int size;
|
||||||
uint8_t *ptr;
|
uint8_t *ptr;
|
||||||
uint64_t v64;
|
uint64_t v64;
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
|
@ -50703,12 +50705,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
|
||||||
v64 = u.u64;
|
v64 = u.u64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is_swap = FALSE;
|
littleEndian = argc > 2 && JS_ToBool(ctx, argv[2]);
|
||||||
if (argc > 2)
|
is_swap = littleEndian ^ !is_be();
|
||||||
is_swap = JS_ToBool(ctx, argv[2]);
|
|
||||||
#ifndef WORDS_BIGENDIAN
|
|
||||||
is_swap ^= 1;
|
|
||||||
#endif
|
|
||||||
abuf = ta->buffer->u.array_buffer;
|
abuf = ta->buffer->u.array_buffer;
|
||||||
if (abuf->detached)
|
if (abuf->detached)
|
||||||
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
|
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
|
||||||
|
|
Loading…
Reference in a new issue