tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] [tcc-win32] compiler generate wrong instruction seque


From: address@hidden
Subject: Re: [Tinycc-devel] [tcc-win32] compiler generate wrong instruction sequence
Date: Fri, 20 Dec 2024 11:36:21 +0800

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



kbkpbot@sina.com
 
From: kbkpbot@sina.com
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:   ...




kbkpbot@sina.com
 
Date: 2024-12-20 10:15
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.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]