A more simple testcase :
#include <stdio.h>
struct string {
char *str;
int len;
};
void dummy(struct string fpath, int dump_arg) {
}
int main() {
int a = 1;
struct string x;
x.str = "gg.v";
x.len = 4;
dummy(x, a == 0);
printf("done\n");
return 0;
}
run this will cause invalid memory also:
bug_tcc.c:16: at main: RUNTIME ERROR: invalid memory access
[email protected]
From: [email protected]
Date: 2024-12-20 10:45
To: tinycc-devel
Subject: Re: [Tinycc-devel] [tcc-win32] compiler generate wrong instruction
sequence
By a quick search the commits, I found this bug was introduced by commit
8227db3a23fd3cf11840eaa25eab5f3f5f813ac7:
commit 8227db3a23fd3cf11840eaa25eab5f3f5f813ac7
Author: grischka <grischka>
Date: Sat Jun 22 11:45:35 2019 +0200
jump optimizations
This unifies VT_CMP with VT_JMP(i) by using mostly VT_CMP
with both a positive and a negative jump target list.
Such we can delay putting the non-inverted or inverted jump
until we can see which one is nore suitable (in most cases).
example:
if (a && b || c && d)
e = 0;
before this patch:
a: 8b 45 fc mov 0xfffffffc(%ebp),%eax
d: 83 f8 00 cmp $0x0,%eax
10: 0f 84 11 00 00 00 je 27 <main+0x27>
16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
19: 83 f8 00 cmp $0x0,%eax
1c: 0f 84 05 00 00 00 je 27 <main+0x27>
22: e9 22 00 00 00 jmp 49 <main+0x49>
27: 8b 45 f4 mov 0xfffffff4(%ebp),%eax
2a: 83 f8 00 cmp $0x0,%eax
2d: 0f 84 11 00 00 00 je 44 <main+0x44>
33: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
36: 83 f8 00 cmp $0x0,%eax
39: 0f 84 05 00 00 00 je 44 <main+0x44>
3f: e9 05 00 00 00 jmp 49 <main+0x49>
44: e9 08 00 00 00 jmp 51 <main+0x51>
49: b8 00 00 00 00 mov $0x0,%eax
4e: 89 45 ec mov %eax,0xffffffec(%ebp)
51: ...
with this patch:
a: 8b 45 fc mov 0xfffffffc(%ebp),%eax
d: 83 f8 00 cmp $0x0,%eax
10: 0f 84 0c 00 00 00 je 22 <main+0x22>
16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
19: 83 f8 00 cmp $0x0,%eax
1c: 0f 85 18 00 00 00 jne 3a <main+0x3a>
22: 8b 45 f4 mov 0xfffffff4(%ebp),%eax
25: 83 f8 00 cmp $0x0,%eax
28: 0f 84 14 00 00 00 je 42 <main+0x42>
2e: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
31: 83 f8 00 cmp $0x0,%eax
34: 0f 84 08 00 00 00 je 42 <main+0x42>
3a: b8 00 00 00 00 mov $0x0,%eax
3f: 89 45 ec mov %eax,0xffffffec(%ebp)
42: ...
[email protected]
From: [email protected]
Date: 2024-12-20 10:15
To: tinycc-devel
Subject: [Tinycc-devel] [tcc-win32] compiler generate wrong instruction sequence
It was only detected under Windows.
bug_tcc.c:
typedef unsigned char* byteptr;
typedef unsigned char u8;
struct string {
u8* str;
int len;
};
typedef struct string string;
#define _SLIT(s) ((string){ \
.str=(byteptr)("" s), \
.len=(sizeof(s)-1)})
int _v_dump_expr_int(string fpath, int dump_arg) {
return 0;
}
void main() {
int a = 1;
_v_dump_expr_int(_SLIT("gg.v"), (a==0 ? (0) : (1)));
}
compile it with following command:
tcc.exe -bt bug_tcc.c
run it, will cause an Error:
bug_tcc.c:19: at main: RUNTIME ERROR: invalid memory access
By disassemble the bug_tcc.exe file, it is shown that the compiler generate a
wrong instruction sequence:
.text:0000000000401024 var_30 = byte ptr -30h
.text:0000000000401024 var_18 = qword ptr -18h
.text:0000000000401024 var_10 = dword ptr -10h
.text:0000000000401024 var_4 = dword ptr -4
.text:0000000000401024
.text:0000000000401024 push rbp
.text:0000000000401025 mov rbp, rsp
.text:0000000000401028 sub rsp, 50h
.text:000000000040102F mov eax, 1
.text:0000000000401034 mov [rbp+var_4], eax
.text:0000000000401037 mov eax, 10h
.text:000000000040103C mov r8, rax ; Size
.text:000000000040103F mov eax, 0
.text:0000000000401044 mov r11, rax
.text:0000000000401047 lea rax, [rbp+var_18]
.text:000000000040104B mov r10, rax
.text:000000000040104E mov rcx, r10 ; void *
.text:0000000000401051 mov rdx, r11 ; Val
.text:0000000000401054 call memset
.text:0000000000401059 lea rax, aGgV ; "gg.v"
.text:0000000000401060 mov [rbp+var_18], rax
.text:0000000000401064 mov eax, 4
.text:0000000000401069 mov [rbp+var_10], eax
.text:000000000040106C mov eax, [rbp+var_4]
.text:000000000040106F cmp eax, 0
.text:0000000000401072 jnz loc_40107D
.text:0000000000401078 jmp loc_401082
.text:000000000040107D ;
---------------------------------------------------------------------------
.text:000000000040107D
.text:000000000040107D loc_40107D: ; CODE XREF:
sub_401024+4E↑j
.text:000000000040107D jmp loc_40108E
.text:0000000000401082 ;
---------------------------------------------------------------------------
.text:0000000000401082
.text:0000000000401082 loc_401082: ; CODE XREF:
sub_401024+54↑j
.text:0000000000401082 lea rax, [rsp+50h+var_30]
// this instruction should move outside...
.text:0000000000401087 mov eax, 0
// BUG!!! overwrite the rax/eax,
this will cause invalid memory access
.text:000000000040108C jmp short loc_401093
.text:000000000040108E ;
---------------------------------------------------------------------------
.text:000000000040108E
.text:000000000040108E loc_40108E: ; CODE XREF:
sub_401024:loc_40107D↑j
.text:000000000040108E mov eax, 1
.text:0000000000401093
.text:0000000000401093 loc_401093: ; CODE XREF:
sub_401024+68↑j
.text:0000000000401093 push rsi
.text:0000000000401094 push rdi
.text:0000000000401095 lea rsi, [rbp+var_18]
.text:0000000000401099 mov rdi, rax
// Because rax was overwrite to zero,
it will fail at movsq
.text:000000000040109C movsq
.text:000000000040109E movsq
.text:00000000004010A0 pop rdi
.text:00000000004010A1 pop rsi
.text:00000000004010A2 mov r11, rax
.text:00000000004010A5 lea r10, [rsp+50h+var_30]
.text:00000000004010AA mov rcx, r10
.text:00000000004010AD mov rdx, r11
.text:00000000004010B0 call sub_401000
.text:00000000004010B5 leave
.text:00000000004010B6 retn
.text:00000000004010B6 sub_401024 endp
Hope someone can fix it.
_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel