Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The idv/idiv instruction is not handled correctly #13

Open
ret2dir opened this issue Oct 4, 2021 · 0 comments
Open

The idv/idiv instruction is not handled correctly #13

ret2dir opened this issue Oct 4, 2021 · 0 comments

Comments

@ret2dir
Copy link

ret2dir commented Oct 4, 2021

We found a possible bug while using symqemu to execute following program:

#include <unistd.h>
#include "csmith.h"
/* --- GLOBAL VARIABLES --- */
static uint16_t g_5[4] = {2,2,6,2};
static int16_t g_81 = 5;
static int32_t g_318 = 6;
/* --- FORWARD DECLARATIONS --- */
static uint32_t  func_1();
static uint8_t  func_2(int16_t  p_3, uint16_t  p_4);

static uint32_t  func_1()
{ /* block id 0 */
    int32_t *l_317 = &g_318;
    *l_317 = func_2(g_5, g_5[3]) != 0;
}
static uint8_t  func_2(int16_t  p_3, uint16_t  p_4)
{ /* block id 1 */
    if (g_5[3])
    { /* block id 3 */
        int32_t l_152[7][2] ;
        l_152[6][0] = 0 > (5 % (0 , p_4) != g_81);
    }
}
/* 
 */
void  main ()
{
    read(STDIN_FILENO, &g_5, sizeof(g_5));
    read(STDIN_FILENO, &g_81, sizeof(g_81));
    read(STDIN_FILENO, &g_318, sizeof(g_318));
    int print_hash_value = 0;
    func_1();
    exit(0);
}

If we compile this code with clang-10, the % operation at line 21 will be trasnlated into idiv assembly instruction.

.text:0000000000401210 55                                      push    rbp
.text:0000000000401211 48 89 E5                                mov     rbp, rsp
.text:0000000000401214 66 89 7D FC                             mov     [rbp+var_4], di
.text:0000000000401218 66 89 75 FA                             mov     [rbp+var_6], si
.text:000000000040121C 66 83 3C 25 3E 40 40 00+                cmp     word_40403E, 0
.text:0000000000401225 0F 84 3D 00 00 00                       jz      loc_401268
.text:000000000040122B 31 C0                                   xor     eax, eax
.text:000000000040122D 0F B7 4D FA                             movzx   ecx, [rbp+var_6]
.text:0000000000401231 BA 05 00 00 00                          mov     edx, 5
.text:0000000000401236 89 45 BC                                mov     [rbp+var_44], eax
.text:0000000000401239 89 D0                                   mov     eax, edx
.text:000000000040123B 99                                      cdq
.text:000000000040123C F7 F9                                   idiv    ecx
.text:000000000040123E 0F BF 0C 25 40 40 40 00                 movsx   ecx, g_81
.text:0000000000401246 39 CA                                   cmp     edx, ecx
.text:0000000000401248 40 0F 95 C6                             setnz   sil
.text:000000000040124C 40 80 E6 01                             and     sil, 1
.text:0000000000401250 40 0F B6 CE                             movzx   ecx, sil
.text:0000000000401254 8B 55 BC                                mov     edx, [rbp+var_44]
.text:0000000000401257 39 CA                                   cmp     edx, ecx
.text:0000000000401259 40 0F 9F C6                             setnle  sil
.text:000000000040125D 40 80 E6 01                             and     sil, 1
.text:0000000000401261 40 0F B6 CE                             movzx   ecx, sil
.text:0000000000401265 89 4D F0                                mov     [rbp+var_10], ecx

However, we noticed that the idiv instruction will be translated into a function call to idivl_EAX by QEMU (see the translation), and this kind of translation is not handled by symqemu, i.e., the divisor and dividend are treated as concrete values, the tcg_gen_div_i32 function defined at tcg-op.c is not used.

For example, the above idiv ecx instruction will be converted to following tcg ops by symqemu:

...

---- 000000000040123b 0000000000000031
 movi_i64 tmp12,$0x4                      pref=0x40
 call sym_sext,$0x5,$1,tmp0_expr,rax_expr,tmp12  dead: 1 2  pref=none
 movi_i64 tmp12_expr,$0x0                 pref=0x2
 movi_i64 tmp12,$0x1f                     pref=0x4
 call sym_arithmetic_shift_right_i64,$0x5,$1,tmp0_expr,rdx,tmp0_expr,tmp12,tmp12_expr  dead: 1 2 3 4  pref=none
 movi_i64 tmp12,$0x4                      pref=0x40
 call sym_zext,$0x5,$1,rdx_expr,tmp0_expr,tmp12  sync: 0  dead: 0 1 2  pref=none
 movi_i64 rdx,$0x0                        sync: 0  dead: 0  pref=0xffff

 ---- 000000000040123c 0000000000000031
 call idivl_EAX,$0x0,$0,env,rcx           dead: 0 1

 ---- 000000000040123e 0000000000000031
 movi_i64 tmp2_expr,$0x0                  pref=0xf038
 movi_i64 tmp2,$0x404040                  pref=0xf038
 qemu_ld_i64 tmp0,tmp2,lesw,0             pref=0xf038
 movi_i64 tmp12,$0x0                      pref=0x100
 movi_i64 tmp13,$0x2                      pref=0x2
 call sym_load_guest_i64,$0x1,$1,tmp0_expr,env,tmp2,tmp2_expr,tmp13,tmp12  dead: 2 3 4 5  pref=none
 movi_i64 tmp12,$0x4                      pref=0x40
 call sym_zext,$0x5,$1,rcx_expr,tmp0_expr,tmp12  dead: 1 2  pref=none
 ext32u_i64 rcx,tmp0                      dead: 1  pref=0xf03c

 ...

The rdx will be updated by idivl_EAX, but the rdx_expr is not updated, so the symbolic chain is broken, and some variables become constant in constraints generated by symqemu.

The same issue exists for the div instruction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant