Compare commits

...
5 Commits
8 changed files with 336 additions and 58 deletions

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
project(
'r2hermes',
'c',
version: '1.2.2',
version: '1.2.4',
license: 'MIT',
default_options: [
'c_std=c11',
+11 -12
View File
@@ -233,11 +233,10 @@ static Result emit_call_fixed(TokenString *out, const ParsedInstruction *insn, i
static Result emit_call_with_argc(TokenString *out, const ParsedInstruction *insn) {
RETURN_IF_ERROR (add (out, reg_l_safe (insn, 0)));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
RETURN_IF_ERROR (add (out, reg_r_safe (insn, 0)));
RETURN_IF_ERROR (add (out, create_left_parenthesis_token ()));
RETURN_IF_ERROR (add (out, reg_r_safe (insn, 1)));
RETURN_IF_ERROR (add (out, create_left_parenthesis_token ()));
char buf2[32];
snprintf (buf2, sizeof (buf2), ", /*argc:%u*/", (unsigned)insn->arg3);
snprintf (buf2, sizeof (buf2), "/*argc:%u*/", (unsigned)insn->arg3);
RETURN_IF_ERROR (add (out, create_raw_token (buf2)));
return add (out, create_right_parenthesis_token ());
}
@@ -685,12 +684,12 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
RETURN_IF_ERROR (add (out, reg_l_safe (insn_c, 0)));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
StringBuffer sb;
_hbc_string_buffer_init (&sb, 48);
RETURN_IF_ERROR (_hbc_string_buffer_init (&sb, 48));
_hbc_string_buffer_append (&sb, "try_get(");
char nb[16];
snprintf (nb, sizeof (nb), "r%u", (unsigned)insn->arg2);
_hbc_string_buffer_append (&sb, nb);
_hbc_format_property_from_string_id (insn->hbc_reader, (op == OP_TryGetById)? insn->arg4: insn->arg4, &sb);
_hbc_format_property_from_string_id (insn->hbc_reader, insn->arg4, &sb);
_hbc_string_buffer_append (&sb, ")");
Token *t = create_raw_token (sb.data? sb.data: "try_get(r0)");
_hbc_string_buffer_free (&sb);
@@ -724,13 +723,13 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
case OP_PutOwnByIndex:
case OP_PutOwnByIndexL:
{
/* obj[idx] = value */
/* obj[idx] = value; operands: obj reg, value reg, literal idx */
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 0)));
RETURN_IF_ERROR (add (out, create_raw_token ("[")));
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 1)));
RETURN_IF_ERROR (add (out, num_token_u32 (insn->arg3)));
RETURN_IF_ERROR (add (out, create_raw_token ("]")));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 2)));
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 1)));
break;
}
case OP_PutByVal:
@@ -750,7 +749,7 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
/* rObj["name"] = rVal */
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 0)));
RETURN_IF_ERROR (add (out, create_raw_token ("[")));
u32 sid = (op == OP_PutById)? insn->arg4: insn->arg4;
u32 sid = insn->arg4;
RETURN_IF_ERROR (add (out, quoted_string (insn->hbc_reader, sid)));
RETURN_IF_ERROR (add (out, create_raw_token ("]")));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
@@ -1098,10 +1097,10 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
RETURN_IF_ERROR (add (out, reg_l_safe (insn_c, 0)));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
RETURN_IF_ERROR (add (out, create_raw_token ("fn_")));
RETURN_IF_ERROR (add (out, num_token_u32 ((op == OP_CallDirect)? insn->arg4: insn->arg4)));
RETURN_IF_ERROR (add (out, num_token_u32 (insn->arg3)));
RETURN_IF_ERROR (add (out, create_left_parenthesis_token ()));
RETURN_IF_ERROR (add (out, create_raw_token ("/*argc:")));
RETURN_IF_ERROR (add (out, num_token_u32 (insn->arg3)));
RETURN_IF_ERROR (add (out, num_token_u32 (insn->arg2)));
RETURN_IF_ERROR (add (out, create_raw_token ("*/")));
RETURN_IF_ERROR (add (out, create_right_parenthesis_token ()));
break;
@@ -1340,7 +1339,7 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
/* Fallback: emit a comment-like raw token with mnemonic */
StringBuffer sb;
_hbc_string_buffer_init (&sb, 64);
RETURN_IF_ERROR (_hbc_string_buffer_init (&sb, 64));
_hbc_string_buffer_append (&sb, "/* ");
_hbc_string_buffer_append (&sb, insn->inst->name);
_hbc_string_buffer_append (&sb, " */");
+4 -1
View File
@@ -455,10 +455,13 @@ Result hbc_dec(const HBCDecodeCtx *ctx, HBCInsnInfo *out) {
switch (operand_type) {
case OPERAND_TYPE_REG8:
case OPERAND_TYPE_UINT8:
case OPERAND_TYPE_ADDR8:
operand_values[i] = ctx->bytes[pos];
pos += 1;
break;
case OPERAND_TYPE_ADDR8:
operand_values[i] = (u32)(i32)(i8)ctx->bytes[pos];
pos += 1;
break;
case OPERAND_TYPE_UINT16:
operand_values[i] = ctx->bytes[pos] | (ctx->bytes[pos + 1] << 8);
pos += 2;
+15 -13
View File
@@ -131,7 +131,7 @@ Result hbc_encoder_parse_instruction(HBCEncoder *encoder, const char *asm_line,
}
/* Parse operands separated by commas */
while (*line && operand_count < 6) {
while (*line) {
/* Skip whitespace */
while (*line && isspace (*line)) {
line++;
@@ -177,13 +177,16 @@ Result hbc_encoder_parse_instruction(HBCEncoder *encoder, const char *asm_line,
}
*trim_end = '\0';
/* Parse operand based on expected type */
if (operand_count < 6 && inst->operands[operand_count].operand_type != OPERAND_TYPE_NONE) {
OperandType expected_type = inst->operands[operand_count].operand_type;
char *endptr;
bool parse_success = false;
if (operand_count >= 6 || inst->operands[operand_count].operand_type == OPERAND_TYPE_NONE) {
return ERROR_RESULT (RESULT_ERROR_PARSING_FAILED, "Incorrect number of operands");
}
switch (expected_type) {
/* Parse operand based on expected type */
OperandType expected_type = inst->operands[operand_count].operand_type;
char *endptr;
bool parse_success = false;
switch (expected_type) {
case OPERAND_TYPE_REG8:
case OPERAND_TYPE_REG32:
/* Register: rN or RN */
@@ -268,13 +271,12 @@ Result hbc_encoder_parse_instruction(HBCEncoder *encoder, const char *asm_line,
break;
}
if (!parse_success) {
return ERROR_RESULT (RESULT_ERROR_PARSING_FAILED, "Invalid operand format");
}
operand_count++;
if (!parse_success) {
return ERROR_RESULT (RESULT_ERROR_PARSING_FAILED, "Invalid operand format");
}
operand_count++;
/* Move to next operand */
line = operand_end;
if (*line == ',') {
@@ -338,7 +340,7 @@ Result hbc_encoder_encode_instruction(HBCEncoder *encoder, const HBCEncodedInstr
/* Write operands based on their types */
for (int i = 0; i < 6 && inst->operands[i].operand_type != OPERAND_TYPE_NONE; i++) {
OperandType type = inst->operands[i].operand_type;
u32 value = operand_values[i];
u64 value = operand_values[i];
switch (type) {
case OPERAND_TYPE_REG8:
+6 -13
View File
@@ -984,12 +984,9 @@ Result _hbc_reader_read_string_tables(HBCReader *reader) {
is_utf16 = reader->small_string_table[i].isUTF16;
}
size_t decoded_length = (size_t)length;
size_t available = (size_t)offset > string_storage_size? 0: string_storage_size - (size_t)offset;
if ((size_t)offset > string_storage_size ||
decoded_length == SIZE_MAX ||
(is_utf16 && decoded_length > available / 2) ||
(!is_utf16 && decoded_length > available)) {
/* Overflow-safe bounds check via subtraction */
const u32 bpc = is_utf16? 2: 1;
if (offset > string_storage_size || length > (string_storage_size - offset) / bpc) {
fprintf (stderr, "Warning: String %u offset/length out of bounds, treating as empty string\n", i);
reader->strings[i] = strdup ("");
if (!reader->strings[i]) {
@@ -1000,9 +997,7 @@ Result _hbc_reader_read_string_tables(HBCReader *reader) {
continue;
}
/* Allocate string buffer (+1 for null terminator) */
size_t buffer_size = decoded_length + 1;
char *str = (char *)malloc (buffer_size);
char *str = (char *)malloc (length * bpc + 1);
if (!str) {
free (string_storage);
reader->string_table_storage = NULL;
@@ -1339,10 +1334,8 @@ Result _hbc_reader_read_bigints(HBCReader *reader) {
u32 offset = bigint_table[i].offset;
u32 length = bigint_table[i].length;
/* Check bounds */
size_t bigint_available = (size_t)offset > reader->header.bigIntStorageSize? 0:
(size_t)reader->header.bigIntStorageSize - (size_t)offset;
if ((size_t)offset > reader->header.bigIntStorageSize || (size_t)length > bigint_available) {
/* Overflow-safe bounds check via subtraction */
if (offset > reader->header.bigIntStorageSize || length > reader->header.bigIntStorageSize - offset) {
fprintf (stderr, "Warning: BigInt %u has invalid offset/length (%u+%u exceeds %u)\n", i, offset, length, reader->header.bigIntStorageSize);
/* Use zero for this value */
reader->bigint_values[i] = 0;
+4 -7
View File
@@ -363,11 +363,9 @@ Result _hbc_generate_r2_script(const char *input_file, const char *output_file)
u32 length = string_infos[i].length;
bool isUTF16 = string_infos[i].isUTF16;
/* Skip strings with obviously invalid offsets/lengths */
size_t available = (size_t)offset > string_storage_size? 0: string_storage_size - (size_t)offset;
if ((size_t)offset > string_storage_size ||
(isUTF16 && (size_t)length > available / 2) ||
(!isUTF16 && (size_t)length > available)) {
/* Overflow-safe bounds check via subtraction */
const u32 bpc = isUTF16? 2: 1;
if (offset > string_storage_size || length > (string_storage_size - offset) / bpc) {
continue;
}
@@ -433,9 +431,8 @@ Result _hbc_generate_r2_script(const char *input_file, const char *output_file)
snprintf (unique_name, sizeof (unique_name), "%s_%u", sanitized_name[0]? sanitized_name: "str", i);
/* Write the string flag - offset is relative to string storage base */
size_t size = isUTF16? (size_t)length * 2: (size_t)length;
uint32_t addr = (unsigned long) (reader.file_buffer.position - string_storage_size + offset);
fprintf (out, "'f str.%s %zu 0x%08x\n", unique_name, size, addr);
fprintf (out, "'f str.%s %u 0x%08x\n", unique_name, length * bpc, addr);
#if 0
/* Add flag for string length */
if (isUTF16) {
+7 -10
View File
@@ -285,21 +285,18 @@ static RList *strings(RBinFile *bf) {
if (hbc_get_string_meta (hbc, i, &meta).code != RESULT_SUCCESS) {
continue;
}
if (meta.length == 0) {
const size_t str_len = strlen (str);
if (str_len == 0) {
continue;
}
RBinString *ptr = R_NEW0 (RBinString);
if (meta.length >= R_BIN_SIZEOF_STRINGS) {
ptr->string = r_str_ndup (str, R_BIN_SIZEOF_STRINGS - 4);
if (ptr->string) {
char *tmp = r_str_newf ("%s...", ptr->string);
free (ptr->string);
ptr->string = tmp;
}
if (str_len >= R_BIN_SIZEOF_STRINGS) {
char *trunc = r_str_ndup (str, R_BIN_SIZEOF_STRINGS - 4);
ptr->string = r_str_newf ("%s...", trunc? trunc: "");
free (trunc);
} else {
ptr->string = r_str_ndup (str, meta.length);
ptr->string = r_str_ndup (str, str_len);
}
if (!ptr->string) {
free (ptr);
+288 -1
View File
@@ -284,7 +284,7 @@ EXPECT=<<EOF
EOF
RUN
NAME=hbc assembler
NAME=hbc pa ret
FILE=--
CMDS=<<EOF
-a hbc
@@ -294,3 +294,290 @@ EXPECT=<<EOF
5c00
EOF
RUN
NAME=hbc pa get_global_object
FILE=--
CMDS=<<EOF
-a hbc
pa get_global_object r0
EOF
EXPECT=<<EOF
3000
EOF
RUN
NAME=hbc pa mov two regs
FILE=--
CMDS=<<EOF
-a hbc
pa mov r2, r1
EOF
EXPECT=<<EOF
080201
EOF
RUN
NAME=hbc pa construct three operands
FILE=--
CMDS=<<EOF
-a hbc
pa construct r0, r0, 1
EOF
EXPECT=<<EOF
50000001
EOF
RUN
NAME=hbc pa select_object three regs
FILE=--
CMDS=<<EOF
-a hbc
pa select_object r0, r1, r0
EOF
EXPECT=<<EOF
6b000100
EOF
RUN
NAME=hbc pa store_to_environment
FILE=--
CMDS=<<EOF
-a hbc
pa store_to_environment r1, 1, r0
EOF
EXPECT=<<EOF
2a010100
EOF
RUN
NAME=hbc pa rejects extra operand
FILE=--
CMDS=<<EOF
-a hbc
"pa ret r0, r1"
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects multiple extra operands
FILE=--
CMDS=<<EOF
-a hbc
"pa ret r0, r1, r2"
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects extra operand on zero-arg instr
FILE=--
CMDS=<<EOF
-a hbc
"pa get_global_object r0, r1"
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects missing operand
FILE=--
CMDS=<<EOF
-a hbc
pa ret
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects truncated mov
FILE=--
CMDS=<<EOF
-a hbc
pa mov r2
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects unknown mnemonic
FILE=--
CMDS=<<EOF
-a hbc
pa bogus_op r0
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pad ret
FILE=--
CMDS=<<EOF
-a hbc
pad 5c00
EOF
EXPECT=<<EOF
ret r0
EOF
RUN
NAME=hbc pad get_global_object
FILE=--
CMDS=<<EOF
-a hbc
pad 3000
EOF
EXPECT=<<EOF
get_global_object r0
EOF
RUN
NAME=hbc pad mov
FILE=--
CMDS=<<EOF
-a hbc
pad 080201
EOF
EXPECT=<<EOF
mov r2, r1
EOF
RUN
NAME=hbc pad construct
FILE=--
CMDS=<<EOF
-a hbc
pad 50000001
EOF
EXPECT=<<EOF
construct r0, r0, 1
EOF
RUN
NAME=hbc pad select_object
FILE=--
CMDS=<<EOF
-a hbc
pad 6b000100
EOF
EXPECT=<<EOF
select_object r0, r1, r0
EOF
RUN
NAME=hbc pad store_to_environment
FILE=--
CMDS=<<EOF
-a hbc
pad 2a010100
EOF
EXPECT=<<EOF
store_to_environment r1, 1, r0
EOF
RUN
NAME=hbc pa+pad roundtrip ret
FILE=--
CMDS=<<EOF
-a hbc
pad `pa ret r0`
EOF
EXPECT=<<EOF
ret r0
EOF
RUN
NAME=hbc pa+pad roundtrip mov
FILE=--
CMDS=<<EOF
-a hbc
pad `pa mov r2, r1`
EOF
EXPECT=<<EOF
mov r2, r1
EOF
RUN
NAME=hbc pa+pad roundtrip construct
FILE=--
CMDS=<<EOF
-a hbc
pad `pa construct r0, r0, 1`
EOF
EXPECT=<<EOF
construct r0, r0, 1
EOF
RUN
NAME=hbc pi ret after wx
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx 5c00
pi 1
EOF
EXPECT=<<EOF
ret r0
EOF
RUN
NAME=hbc pi mov after wx
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx 080201
pi 1
EOF
EXPECT=<<EOF
mov r2, r1
EOF
RUN
NAME=hbc pi construct after wx
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx 50000001
pi 1
EOF
EXPECT=<<EOF
construct r0, r0, 1
EOF
RUN
NAME=hbc pa+wx+pi roundtrip ret
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx `pa ret r0`
pi 1
EOF
EXPECT=<<EOF
ret r0
EOF
RUN
NAME=hbc pa+wx+pi roundtrip mov
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx `pa mov r2, r1`
pi 1
EOF
EXPECT=<<EOF
mov r2, r1
EOF
RUN
NAME=hbc pa+wx+pi roundtrip store_to_environment
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx `pa store_to_environment r1, 1, r0`
pi 1
EOF
EXPECT=<<EOF
store_to_environment r1, 1, r0
EOF
RUN