Skip to content

Commit

Permalink
portability: Fix support for byteswapped output
Browse files Browse the repository at this point in the history
  • Loading branch information
oleavr committed May 27, 2022
1 parent 44f1648 commit f67fb61
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 6 deletions.
3 changes: 0 additions & 3 deletions cutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@
#include <sys/time.h>
#endif

/* set if CPU is big endian */
#undef WORDS_BIGENDIAN

#ifdef _MSC_VER
#define likely(x) (x)
#define unlikely(x) (x)
Expand Down
82 changes: 82 additions & 0 deletions libregexp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2555,6 +2555,88 @@ const char *lre_get_groupnames(const uint8_t *bc_buf)
return (const char *)(bc_buf + 7 + re_bytecode_len);
}

void lre_byte_swap(uint8_t *bc_buf, int bc_buf_len)
{
uint8_t *pc = bc_buf;
uint8_t *end = bc_buf + bc_buf_len;
int len, opcode, n, i;

assert(bc_buf_len > RE_HEADER_LEN);

pc += 3;

len = get_u32(pc);
assert(len == bc_buf_len - RE_HEADER_LEN);
put_u32(pc, bswap32(len));
pc += 4;

while (pc < end) {
opcode = *pc++;
assert(opcode < REOP_COUNT);

len = reopcode_info[opcode].size - 1;
assert(pc + len <= bc_buf + bc_buf_len);

switch(opcode) {
case REOP_char:
put_u16(pc, bswap16(get_u16(pc)));
break;
case REOP_char32:
case REOP_goto:
case REOP_split_goto_first:
case REOP_split_next_first:
case REOP_loop:
case REOP_push_i32:
case REOP_lookahead:
case REOP_negative_lookahead:
case REOP_bne_char_pos:
put_u32(pc, bswap32(get_u32(pc)));
break;
case REOP_range:
n = get_u16(pc);
put_u16(pc, bswap16(n));
pc += 2;

for(i = 0; i < n * 2; i++) {
put_u16(pc, bswap16(get_u16(pc)));
pc += 2;
}

len = 0;

break;
case REOP_range32:
n = get_u16(pc);
put_u16(pc, bswap16(n));
pc += 2;

for(i = 0; i < n * 2; i++) {
put_u32(pc, bswap32(get_u32(pc)));
pc += 4;
}

len = 0;

break;
case REOP_simple_greedy_quant:
for(i = 0; i < 4; i++) {
put_u32(pc, bswap32(get_u32(pc)));
pc += 4;
}

len = 0;

break;
default:
break;
}

pc += len;
}

assert(pc == end);
}

#ifdef TEST

BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size)
Expand Down
1 change: 1 addition & 0 deletions libregexp.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const char *lre_get_groupnames(const uint8_t *bc_buf);
int lre_exec(uint8_t **capture,
const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
int cbuf_type, void *opaque);
void lre_byte_swap(uint8_t *bc_buf, int bc_buf_len);

int lre_parse_escape(const uint8_t **pp, int allow_utf16);
LRE_BOOL lre_is_space(int c);
Expand Down
4 changes: 4 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ sources = [
cdata = configuration_data()
cdata.set_quoted('CONFIG_VERSION', meson.project_version())

if host_machine.endian() == 'big'
cdata.set('WORDS_BIGENDIAN', 1)
endif

if cc.has_header('unistd.h')
cdata.set('HAVE_UNISTD_H', 1)
endif
Expand Down
83 changes: 80 additions & 3 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -34331,6 +34331,31 @@ static void JS_WriteString(BCWriterState *s, JSString *p)
}
}

static int JS_WriteRegExpByteSwapped(BCWriterState *s, JSValueConst obj)
{
JSString *re_bytecode;
JSValue swapped_val;
JSString *swapped;

re_bytecode = JS_VALUE_GET_STRING(obj);

swapped_val = js_new_string8(s->ctx, re_bytecode->u.str8, re_bytecode->len);
if (JS_IsException(swapped_val))
goto fail;
swapped = JS_VALUE_GET_STRING(swapped_val);

lre_byte_swap(swapped->u.str8, swapped->len);

bc_put_u8(s, BC_TAG_STRING);
JS_WriteString(s, swapped);

JS_FreeValue(s->ctx, swapped_val);

return 0;
fail:
return -1;
}

#ifdef CONFIG_BIGNUM
static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
{
Expand Down Expand Up @@ -34475,6 +34500,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj);
uint32_t flags;
int idx, i;
uint8_t *idx_needs_regexp_bswap = NULL;

bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE);
flags = idx = 0;
Expand Down Expand Up @@ -34545,12 +34571,63 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len);
}

for(i = 0; i < b->cpool_count; i++) {
if (JS_WriteObjectRec(s, b->cpool[i]))
goto fail;
if (s->byte_swap) {
uint8_t *bc_buf = b->byte_code_buf;
int bc_len = b->byte_code_len;
int pos, op;
uint32_t prev_push_const_idx = 0;

pos = 0;
while (pos < bc_len) {
op = bc_buf[pos];

switch(op) {
case OP_push_const:
prev_push_const_idx = get_u32(bc_buf + pos + 1);
break;
case OP_push_const8:
prev_push_const_idx = get_u8(bc_buf + pos + 1);
break;
case OP_regexp:
if (!idx_needs_regexp_bswap) {
idx_needs_regexp_bswap = js_malloc(s->ctx, b->cpool_count);
if (!idx_needs_regexp_bswap)
goto fail;
memset(idx_needs_regexp_bswap, 0, b->cpool_count);
}
idx_needs_regexp_bswap[prev_push_const_idx] = TRUE;
default:
break;
}

pos += short_opcode_info(op).size;
}

if (!idx_needs_regexp_bswap)
goto no_bswap_needed;

for(i = 0; i < b->cpool_count; i++) {
if (idx_needs_regexp_bswap[i]) {
if (JS_WriteRegExpByteSwapped(s, b->cpool[i]))
goto fail;
} else {
if (JS_WriteObjectRec(s, b->cpool[i]))
goto fail;
}
}

js_free(s->ctx, idx_needs_regexp_bswap);
} else {
no_bswap_needed:
for(i = 0; i < b->cpool_count; i++) {
if (JS_WriteObjectRec(s, b->cpool[i]))
goto fail;
}
}

return 0;
fail:
js_free(s->ctx, idx_needs_regexp_bswap);
return -1;
}

Expand Down

0 comments on commit f67fb61

Please sign in to comment.