Skip to content

Commit 22d27a5

Browse files
committed
5.0 luac format
1 parent 12b6915 commit 22d27a5

File tree

4 files changed

+198
-22
lines changed

4 files changed

+198
-22
lines changed

librz/bin/format/luac/luac_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ typedef ut32 LUA_INT;
3636
#define LUAC_DATA "\x19\x93\r\n\x1a\n"
3737
#define LUAC_INT_VALIDATION luac_cast_int(0x5678)
3838
#define LUAC5_INT_VALIDATION luac_cast_int(0x12345678)
39+
#define LUAC0_NUMBER_VALIDATION luac_cast_num(3.14159265358979323846E7)
3940
#define LUAC_NUMBER_VALIDATION luac_cast_num(370.5)
4041
#define LUAC5_NUMBER_VALIDATION luac_cast_num(-370.5)
4142

@@ -72,6 +73,7 @@ typedef struct lua_proto_ex {
7273
ut64 line_defined; ///< line number of function start
7374
ut64 lastline_defined; ///< line number of function end
7475

76+
ut8 nups; ///< 5.0 version
7577
ut8 num_params; ///< number of parameters of this proto
7678
ut8 is_vararg; ///< is variable arg?
7779
ut8 max_stack_size; ///< max stack size

librz/bin/format/luac/parse.c

Lines changed: 125 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,17 @@ static ut64 lua_parse_line_defined(LuaProto *proto, RzBuffer *buffer, ut64 offse
8787
size_offset = lua_parse_number(buffer, &line_defined, offset, data_size, minor);
8888
lua_check_error_offset(size_offset);
8989

90+
/* Set Proto Member */
91+
proto->line_defined = (ut64)line_defined;
92+
93+
if (minor == 0) {
94+
return size_offset;
95+
}
96+
9097
const ut64 delta_offset = lua_parse_number(buffer, &last_line_defined, offset + size_offset, data_size, minor);
9198
lua_check_error_offset(delta_offset);
9299
size_offset += delta_offset;
93100

94-
/* Set Proto Member */
95-
proto->line_defined = (ut64)line_defined;
96101
proto->lastline_defined = (ut64)last_line_defined;
97102
return size_offset;
98103
}
@@ -161,7 +166,7 @@ static ut64 lua_parse_string(RzBuffer *buffer, ut8 **dest, int *str_len, ut64 of
161166
RZ_LOG_ERROR("Cannot store string\n");
162167
}
163168

164-
if ((minor == 2) || (minor == 5))
169+
if (((minor == 0) && (ret_buf_size > 0)) || (minor == 2) || (minor == 5))
165170
offset++;
166171
return offset - base_offset;
167172
}
@@ -181,15 +186,15 @@ static ut64 lua_parse_code(LuaProto *proto, RzBuffer *buffer, ut64 offset, ut64
181186
ut64 aligned_size = (offset + 3) & ~3;
182187
size_offset = aligned_size - offset;
183188
}
184-
185-
ut64 total_size = code_size * 4 + size_offset;
189+
ut8 instruction_size = (minor == 0) ? 8 : 4;
190+
ut64 total_size = code_size * instruction_size + size_offset;
186191
if (total_size + offset > data_size) {
187192
RZ_LOG_ERROR("Truncated Code at [0x%llx]\n", offset);
188193
return 0;
189194
}
190195

191196
/* Set Proto Member */
192-
proto->code_size = code_size * 4;
197+
proto->code_size = code_size * instruction_size;
193198
proto->code_skipped = size_offset;
194199
return total_size;
195200
}
@@ -227,7 +232,7 @@ static ut64 lua_parse_const_entry(const LuaProto *proto, RzBuffer *buffer, ut64
227232
current_entry->tag = LUA_VNUMFLT; // keep the same with 5.4 tag
228233
break;
229234
}
230-
if ((minor == 1) || (minor == 2)) {
235+
if ((minor == 0) || (minor == 1) || (minor == 2)) {
231236
double intPart1;
232237
double r = *(double *)recv_data;
233238
double fractionalPart = modf(r, &intPart1);
@@ -511,7 +516,7 @@ LuaProto *lua_parse_body(RzBuffer *buffer, LuaHeaderInfo *header, ut64 base_offs
511516
/* record offset of main proto */
512517
ret_proto->offset = offset;
513518

514-
if ((minor == 1) || (minor == 3) || (minor == 4)) {
519+
if ((minor == 0) || (minor == 1) || (minor == 3) || (minor == 4)) {
515520
/* parse proto name of main proto */
516521
delta_offset = lua_parse_name(ret_proto, buffer, offset, data_size, minor);
517522
if (minor == 1) {
@@ -531,6 +536,17 @@ LuaProto *lua_parse_body(RzBuffer *buffer, LuaHeaderInfo *header, ut64 base_offs
531536
if ((minor == 1) && (ret_proto->line_defined > 0))
532537
offset++;
533538

539+
if (minor == 0) {
540+
int size_upvalues = 0;
541+
ut8 tmp;
542+
if (!rz_buf_read8_at(buffer, offset, &tmp)) {
543+
return 0;
544+
}
545+
offset++;
546+
size_upvalues = tmp;
547+
(void)size_upvalues;
548+
}
549+
534550
/* parse num params max_stack_size */
535551
if (offset + 3 > data_size) {
536552
lua_free_proto_entry(ret_proto);
@@ -545,19 +561,47 @@ LuaProto *lua_parse_body(RzBuffer *buffer, LuaHeaderInfo *header, ut64 base_offs
545561
}
546562
offset += 3;
547563

564+
if (minor == 0) {
565+
/* parse debug */
566+
ret_proto->debug_offset = offset;
567+
delta_offset = lua_parse_debug(ret_proto, buffer, offset, data_size, minor);
568+
lua_check_error_offset_proto(delta_offset, ret_proto);
569+
offset += delta_offset;
570+
571+
/* parse constants */
572+
ret_proto->const_offset = offset;
573+
delta_offset = lua_parse_consts(ret_proto, buffer, offset, data_size, minor);
574+
lua_check_error_offset_proto(delta_offset, ret_proto);
575+
offset += delta_offset;
576+
577+
/* parse inner protos */
578+
ret_proto->inner_proto_offset = offset;
579+
delta_offset = lua_parse_protos(ret_proto, buffer, header, offset, data_size);
580+
lua_check_error_offset_proto(delta_offset, ret_proto);
581+
offset += delta_offset;
582+
583+
/* specially handle recursive protos size */
584+
ret_proto->inner_proto_size = offset - ret_proto->inner_proto_offset;
585+
}
586+
548587
/* parse code */
549588
ret_proto->code_offset = offset;
550589
delta_offset = lua_parse_code(ret_proto, buffer, offset, data_size, minor);
551590
lua_check_error_offset_proto(delta_offset, ret_proto);
552591
offset += delta_offset;
553592

593+
if (minor == 0) {
594+
ret_proto->size = offset - base_offset + 1;
595+
return ret_proto;
596+
}
597+
554598
/* parse constants */
555599
ret_proto->const_offset = offset;
556600
delta_offset = lua_parse_consts(ret_proto, buffer, offset, data_size, minor);
557601
lua_check_error_offset_proto(delta_offset, ret_proto);
558602
offset += delta_offset;
559603

560-
if (minor <= 2) {
604+
if ((minor == 1) || (minor == 2)) {
561605
/* parse inner protos */
562606
ret_proto->inner_proto_offset = offset;
563607
delta_offset = lua_parse_protos(ret_proto, buffer, header, offset, data_size);
@@ -641,7 +685,7 @@ size_t parse_header(const RzBinFile *bf, LuaHeaderInfo *header) {
641685
return 0;
642686
}
643687

644-
if (minor < 1 || minor > 5) {
688+
if (minor > 5) {
645689
RZ_LOG_ERROR("lua 5.%c not support now\n", header->minor + '0');
646690
return 0;
647691
}
@@ -650,12 +694,16 @@ size_t parse_header(const RzBinFile *bf, LuaHeaderInfo *header) {
650694
CHECK_SIZE;
651695

652696
/* read header members from work buffer */
653-
if (!rz_buf_read8_at(buffer, offset, &header->format)) {
654-
return 0;
697+
/* is official compiler (minor > 0) */
698+
if (minor > 0) {
699+
if (!rz_buf_read8_at(buffer, offset, &header->format)) {
700+
return 0;
701+
}
702+
offset++;
703+
CHECK_SIZE;
655704
}
656-
offset++;
657-
CHECK_SIZE;
658705

706+
/* check luac data if minor > 2 */
659707
if (minor > 2) {
660708
offset += strlen(LUAC_DATA);
661709
} else {
@@ -670,19 +718,18 @@ size_t parse_header(const RzBinFile *bf, LuaHeaderInfo *header) {
670718
/* get int size on 5.1, 5.2, 5.3, 5.5 */
671719
if (minor == 5) {
672720
const ut64 size_offset = lua_parse_szint(buffer, &header->int_size, offset, bf->size, minor);
673-
// printf("size_offset: %llu, offset: %llu\n", size_offset, offset);
674721
offset += size_offset;
675722
CHECK_SIZE;
676723
const ut32 test_valid = lua_load_int(buffer, offset);
677724
(void)test_valid;
678725
offset += header->int_size;
679-
// printf("offset: %llu, int_size: %x, test_valid: %x\n\n", offset, int_size, test_valid);
680726
} else if (minor <= 3) { ///< TODO: ????? need 3?
681727
ut8 tmp;
682728
if (!rz_buf_read8_at(buffer, offset, &tmp)) {
683729
return 0;
684730
}
685731
header->int_size = tmp;
732+
header->integer_size = 4;
686733
offset++;
687734
} else {
688735
header->int_size = 4;
@@ -724,6 +771,46 @@ size_t parse_header(const RzBinFile *bf, LuaHeaderInfo *header) {
724771
CHECK_SIZE;
725772
}
726773

774+
if (minor == 0) {
775+
ut8 tmp;
776+
if (!rz_buf_read8_at(buffer, offset, &tmp)) {
777+
return 0;
778+
}
779+
offset++;
780+
if (tmp != 6) {
781+
RZ_LOG_ERROR("Wrong size of SIZE_OP\n");
782+
return 0;
783+
}
784+
CHECK_SIZE;
785+
if (!rz_buf_read8_at(buffer, offset, &tmp)) {
786+
return 0;
787+
}
788+
offset++;
789+
if (tmp != 8) {
790+
RZ_LOG_ERROR("Wrong size of SIZE_A\n");
791+
return 0;
792+
}
793+
CHECK_SIZE;
794+
if (!rz_buf_read8_at(buffer, offset, &tmp)) {
795+
return 0;
796+
}
797+
offset++;
798+
if (tmp != 9) {
799+
RZ_LOG_ERROR("Wrong size of SIZE_B\n");
800+
return 0;
801+
}
802+
CHECK_SIZE;
803+
if (!rz_buf_read8_at(buffer, offset, &tmp)) {
804+
return 0;
805+
}
806+
offset++;
807+
if (tmp != 9) {
808+
RZ_LOG_ERROR("Wrong size of SIZE_C\n");
809+
return 0;
810+
}
811+
CHECK_SIZE;
812+
}
813+
727814
/* get lua integer size on luac > 5.3 */
728815
if (minor == 5) {
729816
const ut64 size_offset = lua_parse_szint(buffer, &header->integer_size, offset, bf->size, minor);
@@ -772,6 +859,15 @@ size_t parse_header(const RzBinFile *bf, LuaHeaderInfo *header) {
772859
CHECK_SIZE;
773860
header->number_size = tmp;
774861
}
862+
if (minor == 0) {
863+
double number_valid = lua_load_number(buffer, offset);
864+
if (number_valid != LUAC0_NUMBER_VALIDATION) {
865+
RZ_LOG_ERROR("Number format does not match with the expected number (expected: %f, actual: %f)\n", LUAC0_NUMBER_VALIDATION, number_valid);
866+
return 0;
867+
}
868+
offset += header->number_size;
869+
CHECK_SIZE;
870+
}
775871

776872
/* check lua number is integral on 5.1, 5.2 */
777873
if ((minor == 1) || (minor == 2)) {
@@ -860,11 +956,19 @@ RzBinInfo *lua_parse_bin_info(const RzBinFile *bf, const LuaHeaderInfo *header)
860956

861957
/* Check Size */
862958
// TODO : remove this check and process different compiler options
863-
if ((header->instruction_size != sizeof(LUA_INSTRUCTION)) ||
864-
(header->integer_size != sizeof(LUA_INTEGER)) ||
865-
(header->number_size != sizeof(LUA_NUMBER))) {
866-
RZ_LOG_ERROR("Size definition does not match with the expected size\n");
867-
return ret;
959+
if (header->minor == 0) {
960+
if ((header->instruction_size != sizeof(ut64)) ||
961+
(header->number_size != sizeof(LUA_NUMBER))) {
962+
RZ_LOG_ERROR("Size definition does not match with the expected size (minor = 0)\n");
963+
return ret;
964+
}
965+
} else {
966+
if ((header->instruction_size != sizeof(LUA_INSTRUCTION)) ||
967+
(header->integer_size != sizeof(LUA_INTEGER)) ||
968+
(header->number_size != sizeof(LUA_NUMBER))) {
969+
RZ_LOG_ERROR("Size definition does not match with the expected size\n");
970+
return ret;
971+
}
868972
}
869973

870974
if (header->minor < 4) {

librz/bin/p/bin_luac.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,13 @@ static void destroy(RzBinFile *bf) {
115115
static RzStructuredData *get_structured_data_protos(RzStructuredData *parent, LuaProto *proto, st32 minor) {
116116
#ifdef RZ_DEBUG
117117
const char *pnd = proto->proto_name ? rz_str_dup((char *)proto->proto_name + 1) : rz_str_newf("fcn.%08llx", proto->offset);
118+
ut8 instruction_size = (minor == 0) ? 8 : 4;
118119
printf("\n%s <%s:%lld,%lld> (%lld instructions at 0x%p)\n",
119120
(proto->line_defined == 0) ? "main" : "function",
120121
pnd,
121122
proto->line_defined,
122123
proto->lastline_defined,
123-
proto->code_size / 4,
124+
proto->code_size / instruction_size,
124125
&proto);
125126
free((char *)pnd);
126127

test/db/formats/luac/luac

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,72 @@
1+
NAME=LUAC: plugin load 5.0 version
2+
FILE=bins/luac/class50.luac
3+
CMDS=<<EOF
4+
e asm.arch=luac
5+
e asm.bytes=true
6+
iH
7+
EOF
8+
EXPECT=<<EOF
9+
luac-info:
10+
version:
11+
major: 5
12+
minor: 0
13+
compiler: "Official Lua Compiler"
14+
source_file_name: "class.lua"
15+
header_size: 21
16+
body_size: 810
17+
file_size: 831
18+
protos:
19+
fcn.00000016:
20+
proto_name: "main.00000016"
21+
start_line: 0
22+
last_line: 0
23+
instructions: 21
24+
num_params: 0
25+
slots: 3
26+
functions: 2
27+
locals: 0
28+
upvalues: 0
29+
constants_count: 7
30+
constants:
31+
- "Account"
32+
- "__index"
33+
- "create"
34+
- "withdraw"
35+
- "acc"
36+
- 1000
37+
- 100
38+
fcn.000000fc:
39+
proto_name: "fcn.000000fc"
40+
start_line: 4
41+
last_line: 0
42+
instructions: 8
43+
num_params: 2
44+
slots: 6
45+
functions: 0
46+
locals: 3
47+
upvalues: 0
48+
constants_count: 3
49+
constants:
50+
- "setmetatable"
51+
- "Account"
52+
- "balance"
53+
fcn.000001fe:
54+
proto_name: "fcn.000001fe"
55+
start_line: 11
56+
last_line: 0
57+
instructions: 4
58+
num_params: 2
59+
slots: 3
60+
functions: 0
61+
locals: 2
62+
upvalues: 0
63+
constants_count: 1
64+
constants:
65+
- "balance"
66+
67+
EOF
68+
RUN
69+
170
NAME=LUAC: plugin load 5.1 version
271
FILE=bins/luac/class51.luac
372
CMDS=<<EOF

0 commit comments

Comments
 (0)