matt-kempster / m2c

A MIPS and PowerPC decompiler.
GNU General Public License v3.0
386 stars 46 forks source link

[BUG] Missing Stack Variable #261

Open InusualZ opened 1 year ago

InusualZ commented 1 year ago

Bug

In the decompilation, you see this line:

 temp_r0_2 = (sp8 << 8) | sp9;

but the variable sp9 its never declared.

Decompilation

s32 PatCryptDecrypt(s8* data, s16* size) {
    u8 sp10;
    u8 sp8;
    s16 temp_r0_2;
    s16 var_r28;
    s32 var_r29;
    s8* var_r25;
    u16 temp_r3;
    u32 temp_r0;
    u32 temp_r0_3;
    u32 temp_r0_4;
    u32 temp_r3_2;
    u32 temp_r3_3;
    u32 temp_r3_4;

    if ((data == NULL) || (size == NULL) || (temp_r3 = *size, ((temp_r3 == 0) != 0))) {
        return 0;
    }
    temp_r3_2 = temp_r3 >> 0x1F;
    temp_r0 = (temp_r3 << 0x1C) - temp_r3_2;
    if ((((temp_r0 << 4) | (temp_r0 >> 0x1C)) + temp_r3_2) != 0) {
        return 0x80000000;
    }
    memcpy(&sp10, data, 0x10);
    Camellia_DecryptBlock(0x100, &sp10, KeyTable, &sp10);
    memcpy(&sp8, &sp10, 4);
    temp_r0_2 = (sp8 << 8) | sp9;
    var_r29 = 4;
    var_r28 = 0;
    var_r25 = data;
loop_11:
    if ((var_r29 < *size) && (var_r28 < temp_r0_2)) {
        if (var_r28 < temp_r0_2) {
            temp_r3_3 = var_r29 >> 0x1F;
            temp_r0_3 = (var_r29 << 0x1C) - temp_r3_3;
            *var_r25 = (&sp10)[((temp_r0_3 << 4) | (temp_r0_3 >> 0x1C)) + temp_r3_3];
        }
        var_r29 += 1;
        var_r28 += 1;
        var_r25 += 1;
        temp_r3_4 = var_r29 >> 0x1F;
        temp_r0_4 = (var_r29 << 0x1C) - temp_r3_4;
        if ((((temp_r0_4 << 4) | (temp_r0_4 >> 0x1C)) + temp_r3_4) == 0) {
            memcpy(&sp10, &data[var_r29], 0x10);
            Camellia_DecryptBlock(0x100, &sp10, KeyTable + 0x3670, &sp10);
        }
        goto loop_11;
    }
    *size = var_r28;
    return 0;
}

Assembly:

.include "macros.s"

.section .text, "ax"

/* int PatCryptDecrypt(char* data, short* size) */
.global PatCryptDecrypt
PatCryptDecrypt:
/* 8042402C 003E760C  94 21 FF C0 */    stwu r1, -0x40(r1)
/* 80424030 003E7610  7C 08 02 A6 */    mflr r0
/* 80424034 003E7614  90 01 00 44 */    stw r0, 0x44(r1)
/* 80424038 003E7618  39 61 00 40 */    addi r11, r1, 0x40
/* 8042403C 003E761C  48 03 2D C1 */    bl _savegpr_24
/* 80424040 003E7620  7C 7A 1B 78 */    mr r26, r3
/* 80424044 003E7624  7C 9B 23 78 */    mr r27, r4
/* 80424048 003E7628  2C 03 00 00 */    cmpwi r3, 0x0
/* 8042404C 003E762C  41 82 00 18 */    beq lbl_80424064
/* 80424050 003E7630  2C 04 00 00 */    cmpwi r4, 0x0
/* 80424054 003E7634  41 82 00 10 */    beq lbl_80424064
/* 80424058 003E7638  A0 64 00 00 */    lhz r3, 0x0(r4)
/* 8042405C 003E763C  2C 03 00 00 */    cmpwi r3, 0x0
/* 80424060 003E7640  40 82 00 0C */    bne lbl_8042406C
lbl_80424064:
/* 80424064 003E7644  38 60 00 00 */    li r3, 0x0
/* 80424068 003E7648  48 00 01 18 */    b lbl_80424180
lbl_8042406C:
/* 8042406C 003E764C  54 60 E0 06 */    slwi r0, r3, 28
/* 80424070 003E7650  54 63 0F FE */    srwi r3, r3, 31
/* 80424074 003E7654  7C 03 00 50 */    subf r0, r3, r0
/* 80424078 003E7658  54 00 20 3E */    rlwinm r0, r0, 0x4, 0x0, 0x1f
/* 8042407C 003E765C  7C 00 1A 14 */    add r0, r0, r3
/* 80424080 003E7660  2C 00 00 00 */    cmpwi r0, 0x0
/* 80424084 003E7664  41 82 00 0C */    beq lbl_80424090
/* 80424088 003E7668  3C 60 80 00 */    lis r3, 0x8000
/* 8042408C 003E766C  48 00 00 F4 */    b lbl_80424180
lbl_80424090:
/* 80424090 003E7670  38 61 00 10 */    addi r3, r1, 0x10
/* 80424094 003E7674  7F 44 D3 78 */    mr r4, r26
/* 80424098 003E7678  38 A0 00 10 */    li r5, 0x10
/* 8042409C 003E767C  4B BD FF 65 */    bl memcpy
/* 804240A0 003E7680  38 60 01 00 */    li r3, 0x100
/* 804240A4 003E7684  38 81 00 10 */    addi r4, r1, 0x10
/* 804240A8 003E7688  3F C0 80 6D */    lis r30, KeyTable@ha
/* 804240AC 003E768C  38 BE 36 70 */    addi r5, r30, KeyTable@l
/* 804240B0 003E7690  7C 86 23 78 */    mr r6, r4
/* 804240B4 003E7694  4B FF FB D1 */    bl Camellia_DecryptBlock
/* 804240B8 003E7698  38 61 00 08 */    addi r3, r1, 0x8
/* 804240BC 003E769C  38 81 00 10 */    addi r4, r1, 0x10
/* 804240C0 003E76A0  38 A0 00 04 */    li r5, 0x4
/* 804240C4 003E76A4  4B BD FF 3D */    bl memcpy
/* 804240C8 003E76A8  88 01 00 08 */    lbz r0, 0x8(r1)
/* 804240CC 003E76AC  54 03 40 2E */    slwi r3, r0, 8
/* 804240D0 003E76B0  88 01 00 09 */    lbz r0, 0x9(r1)
/* 804240D4 003E76B4  7C 60 03 78 */    or r0, r3, r0
/* 804240D8 003E76B8  54 1F 04 3E */    clrlwi r31, r0, 16
/* 804240DC 003E76BC  3B A0 00 04 */    li r29, 0x4
/* 804240E0 003E76C0  3B 80 00 00 */    li r28, 0x0
/* 804240E4 003E76C4  3B 01 00 10 */    addi r24, r1, 0x10
/* 804240E8 003E76C8  7F 59 D3 78 */    mr r25, r26
/* 804240EC 003E76CC  48 00 00 74 */    b lbl_80424160
lbl_804240F0:
/* 804240F0 003E76D0  7C 1C F8 00 */    cmpw r28, r31
/* 804240F4 003E76D4  40 80 00 20 */    bge lbl_80424114
/* 804240F8 003E76D8  57 A0 E0 06 */    slwi r0, r29, 28
/* 804240FC 003E76DC  57 A3 0F FE */    srwi r3, r29, 31
/* 80424100 003E76E0  7C 03 00 50 */    subf r0, r3, r0
/* 80424104 003E76E4  54 00 20 3E */    rlwinm r0, r0, 0x4, 0x0, 0x1f
/* 80424108 003E76E8  7C 00 1A 14 */    add r0, r0, r3
/* 8042410C 003E76EC  7C 18 00 AE */    lbzx r0, r24, r0
/* 80424110 003E76F0  98 19 00 00 */    stb r0, 0x0(r25)
lbl_80424114:
/* 80424114 003E76F4  3B BD 00 01 */    addi r29, r29, 0x1
/* 80424118 003E76F8  3B 9C 00 01 */    addi r28, r28, 0x1
/* 8042411C 003E76FC  3B 39 00 01 */    addi r25, r25, 0x1
/* 80424120 003E7700  57 A0 E0 06 */    slwi r0, r29, 28
/* 80424124 003E7704  57 A3 0F FE */    srwi r3, r29, 31
/* 80424128 003E7708  7C 03 00 50 */    subf r0, r3, r0
/* 8042412C 003E770C  54 00 20 3E */    rlwinm r0, r0, 0x4, 0x0, 0x1f
/* 80424130 003E7710  7C 00 1A 14 */    add r0, r0, r3
/* 80424134 003E7714  2C 00 00 00 */    cmpwi r0, 0x0
/* 80424138 003E7718  40 82 00 28 */    bne lbl_80424160
/* 8042413C 003E771C  38 61 00 10 */    addi r3, r1, 0x10
/* 80424140 003E7720  7C 9A EA 14 */    add r4, r26, r29
/* 80424144 003E7724  38 A0 00 10 */    li r5, 0x10
/* 80424148 003E7728  4B BD FE B9 */    bl memcpy
/* 8042414C 003E772C  38 60 01 00 */    li r3, 0x100
/* 80424150 003E7730  38 81 00 10 */    addi r4, r1, 0x10
/* 80424154 003E7734  38 BE 36 70 */    addi r5, r30, 0x3670
/* 80424158 003E7738  7C 86 23 78 */    mr r6, r4
/* 8042415C 003E773C  4B FF FB 29 */    bl Camellia_DecryptBlock
lbl_80424160:
/* 80424160 003E7740  A0 1B 00 00 */    lhz r0, 0x0(r27)
/* 80424164 003E7744  7C 1D 00 00 */    cmpw r29, r0
/* 80424168 003E7748  40 80 00 0C */    bge lbl_80424174
/* 8042416C 003E774C  7C 1C F8 00 */    cmpw r28, r31
/* 80424170 003E7750  41 80 FF 80 */    blt lbl_804240F0
lbl_80424174:
/* 80424174 003E7754  57 80 04 3E */    clrlwi r0, r28, 16
/* 80424178 003E7758  B0 1B 00 00 */    sth r0, 0x0(r27)
/* 8042417C 003E775C  38 60 00 00 */    li r3, 0x0
lbl_80424180:
/* 80424180 003E7760  39 61 00 40 */    addi r11, r1, 0x40
/* 80424184 003E7764  48 03 2C C5 */    bl _restgpr_24
/* 80424188 003E7768  80 01 00 44 */    lwz r0, 0x44(r1)
/* 8042418C 003E776C  7C 08 03 A6 */    mtlr r0
/* 80424190 003E7770  38 21 00 40 */    addi r1, r1, 0x40
/* 80424194 003E7774  4E 80 00 20 */    blr

Context

typedef unsigned long size_t;

void* memset(void* dest, int val, size_t count);
void* memcpy(void* dest, const void* src, size_t n);

int PatCryptEncrypt(char* data, short* size);
int PatCryptDecrypt(char* data, short* size);

typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];

KEY_TABLE_TYPE KeyTable;

void Camellia_Ekeygen(const int keyBitLength,
              const unsigned char *rawKey, 
              KEY_TABLE_TYPE keyTable);

void Camellia_EncryptBlock(const int keyBitLength,
               const unsigned char *plaintext, 
               const KEY_TABLE_TYPE keyTable, 
               unsigned char *cipherText);

void Camellia_DecryptBlock(const int keyBitLength, 
               const unsigned char *cipherText, 
               const KEY_TABLE_TYPE keyTable, 
               unsigned char *plaintext);

void _savegpr_14(); // @80456dd4
void _savegpr_15(); // @80456dd8
void _savegpr_16(); // @80456ddc
void _savegpr_17(); // @80456de0
void _savegpr_18(); // @80456de4
void _savegpr_19(); // @80456de8
void _savegpr_20(); // @80456dec
void _savegpr_21(); // @80456df0
void _savegpr_22(); // @80456df4
void _savegpr_23(); // @80456df8
void _savegpr_24(); // @80456dfc
void _savegpr_25(); // @80456e00
void _savegpr_26(); // @80456e04
void _savegpr_27(); // @80456e08

void _restgpr_14(); // @80456e20
void _restgpr_15(); // @80456e24
void _restgpr_16(); // @80456e28
void _restgpr_17(); // @80456e2c
void _restgpr_18(); // @80456e30
void _restgpr_19(); // @80456e34
void _restgpr_20(); // @80456e38
void _restgpr_21(); // @80456e3c
void _restgpr_22(); // @80456e40
void _restgpr_23(); // @80456e44
void _restgpr_24(); // @80456e48
void _restgpr_25(); // @80456e4c
void _restgpr_26(); // @80456e50
void _restgpr_27(); // @80456e54
mkst commented 6 months ago

sp9 is implicit. Looking at the code you can see that sp10 is at least 0x10 big, and sp8 is at least 0x4 big:

memcpy(&sp10, data, 0x10); // copy 16 bytes from data into sp10 -> sp10 must be at least 16 bytes big, e.g. u8 sp10[16];

memcpy(&sp8, &sp10, 4);  // copy 4 bytes from sp10 into sp8 -> sp8 must be at least 4 bytes big, e.g. u8 sp8[4];

This means that

temp_r0_2 = (sp8 << 8) | sp9;

would be

temp_r0_2 = (sp8[0] << 8) | sp8[1];

Are you expecting m2c to create a variable for sp9 (which isn't a real variable) or to know that sp8 is at least size 4, therefore should be a byte array of 4?

simonlindholm commented 6 months ago

235 fixes this by adding a variable declaration for sp9, but I never landed it because on review I started feeling like m2c should do something smarter when it detects stack variables that never get written to/addresses taken.