zrax / pycdc

C++ python bytecode disassembler and decompiler
GNU General Public License v3.0
2.92k stars 584 forks source link

Processing condition incorrectly #468

Open jackyzy823 opened 2 months ago

jackyzy823 commented 2 months ago

Test under Python 3.10

Original file (sample.py)

def sample():
    arg1 = "test"
    if arg1 and not ext_method(ext_arg):
        return 0
    else:
        return ext_method2()

// Decompile with pycdc

Output file

# Source Generated with Decompyle++
# File: sample.cpython-310.pyc (Python 3.10)

def sample():
    arg1 = 'test'
    if not arg1 and ext_method(ext_arg):
        return 0
    return None()

First, the condition is incorrect. Second the ext_method2 become None

Disassmeble with pycdas

sample.cpython-310.pyc (Python 3.10)
[Code]
    File Name: ./sample.py
    Object Name: <module>
    Arg Count: 0
    Pos Only Arg Count: 0
    KW Only Arg Count: 0
    Locals: 0
    Stack Size: 2
    Flags: 0x00000040 (CO_NOFREE)
    [Names]
        'sample'
    [Var Names]
    [Free Vars]
    [Cell Vars]
    [Constants]
        [Code]
            File Name: ./sample.py
            Object Name: sample
            Arg Count: 0
            Pos Only Arg Count: 0
            KW Only Arg Count: 0
            Locals: 1
            Stack Size: 2
            Flags: 0x00000043 (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)
            [Names]
                'ext_method'
                'ext_arg'
                'ext_method2'
            [Var Names]
                'arg1'
            [Free Vars]
            [Cell Vars]
            [Constants]
                None
                'test'
                0
            [Disassembly]
                0       LOAD_CONST                      1: 'test'
                2       STORE_FAST                      0: arg1
                4       LOAD_FAST                       0: arg1
                6       POP_JUMP_IF_FALSE               10 (to 20)
                8       LOAD_GLOBAL                     0: ext_method
                10      LOAD_GLOBAL                     1: ext_arg
                12      CALL_FUNCTION                   1
                14      POP_JUMP_IF_TRUE                10 (to 20)
                16      LOAD_CONST                      2: 0
                18      RETURN_VALUE                    
                20      LOAD_GLOBAL                     2: ext_method2
                22      CALL_FUNCTION                   0
                24      RETURN_VALUE                    
        'sample'
        None
    [Disassembly]
        0       LOAD_CONST                      0: <CODE> sample
        2       LOAD_CONST                      1: 'sample'
        4       MAKE_FUNCTION                   0
        6       STORE_NAME                      0: sample
        8       LOAD_CONST                      2: None
        10      RETURN_VALUE                    
jackyzy823 commented 2 months ago

Simpler code:

a = True
b = False
if a and not b:
    print("In if")
else:
    print("In false")

decompile to

# Source Generated with Decompyle++
# File: sample.cpython-312.pyc (Python 3.12)

a = True
b = False
if not a and b:
    print('In if')
    return None
print('In false')

ASM

sample.cpython-312.pyc (Python 3.12)
[Code]
    File Name: ./sample.py
    Object Name: <module>
    Qualified Name: <module>
    Arg Count: 0
    Pos Only Arg Count: 0
    KW Only Arg Count: 0
    Stack Size: 3
    Flags: 0x00000000
    [Names]
        'a'
        'b'
        'print'
    [Locals+Names]
    [Constants]
        True
        False
        'In if'
        'In false'
        None
    [Disassembly]
        0       RESUME                          0
        2       LOAD_CONST                      0: True
        4       STORE_NAME                      0: a
        6       LOAD_CONST                      1: False
        8       STORE_NAME                      1: b
        10      LOAD_NAME                       0: a
        12      POP_JUMP_IF_FALSE               11 (to 36)
        14      LOAD_NAME                       1: b
        16      POP_JUMP_IF_TRUE                9 (to 36)
        18      PUSH_NULL
        20      LOAD_NAME                       2: print
        22      LOAD_CONST                      2: 'In if'
        24      CALL                            1
        32      POP_TOP
        34      RETURN_CONST                    4: None
        36      PUSH_NULL
        38      LOAD_NAME                       2: print
        40      LOAD_CONST                      3: 'In false'
        42      CALL                            1
        50      POP_TOP
        52      RETURN_CONST                    4: None