LADSoft / OrangeC

OrangeC Compiler And Tool Chain
http://ladsoft.tripod.com/orange_c_compiler.html
Other
300 stars 39 forks source link

XXTEA implementation gives an incorrect answer #1056

Open alvoskov opened 3 days ago

alvoskov commented 3 days ago

The next XXTEA implementation gives incorrect result when compiled by OCC 6.0.73. Compilation in MinGW (both 32-bit and 64-bit), Open Watcom and Pelles C gives correct results.

The program output in OCC:

Test result: 0
0: C4CC7F1CC007378C FFFFFFFFC007378C

The source code:

#include < stdio.h>
#include < stdlib.h>
#include < stdint.h>

#define MX(p) (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[((p)&3)^e] ^ z)))

uint64_t xxtea_encrypt(const uint64_t inp, const uint32_t *key)
{
    static const uint32_t DELTA = 0x9e3779b9;
    static const unsigned int nrounds = 32;
    uint32_t y, z, sum = 0;
    union {
        uint32_t v[2];
        uint64_t x;
    } out;
    out.x = inp;
    z = out.v[1];
    for (unsigned int i = 0; i < nrounds; i++) {
        sum += DELTA;
        unsigned int e = (sum >> 2) & 3;
        y = out.v[1]; 
        z = out.v[0] += MX(0);
        y = out.v[0];
        z = out.v[1] += MX(1);
    }
    return out.x;
}

int xxtea_test()
{
    static const uint64_t OUT0 = 0x575d8c80053704ab;
    static const uint64_t OUT1 = 0xc4cc7f1cc007378c;
    uint32_t key[4] = {0, 0, 0, 0};
    // Test 1
    if (xxtea_encrypt(0, key) != OUT0) {
        fprintf(stderr, "0: %llX %llX", xxtea_encrypt(0, key), OUT0);
        return 0;
    }
    // Test 2
    key[0] = 0x08040201; key[1] = 0x80402010;
    key[2] = 0xf8fcfeff; key[3] = 0x80c0e0f0; 
    if (xxtea_encrypt(0x80c0e0f0f8fcfeff, key) != OUT1) {
        fprintf(stderr, "0: %llX %llX", xxtea_encrypt(0x80c0e0f0f8fcfeff, key), OUT1);
        return 0;
    }
    return 1;
}

int main()
{
    printf("Test result: %d\n", xxtea_test());
}
chuggafan commented 2 days ago

Thank you for the report! I saw your previous issue about the missing math functions, the only reason I'm not tackling that is that I don't know enough about implementing those in order to do anything. Anyways, in this case it looks like the issue is actually with some part of the compilation process (my guess is either optimizer or parser) somehow obliterating the top half of the const variable OUT1, as evidenced by your screenshot, the calculations are all done correctly, but OUT1 had the upper-half of it mistakenly replaced with all 1s and actual output from the compiler in terms of assembly supports this. I still need to get going on my #embed work (I'm going to move the

code to unions temporarily), so I can't personally tackle this at the moment, especially since I'm already being lazy about one thing, no reason to add another thing to be lazy about onto the pile. A quick snippet from `occ /S /O0 xxtea.cpp` source code shows this: ; Line 39: } L_32: ; Line 41: key[0] = 0x08040201; key[1] = 0x80402010; mov dword [ebp-010h],08040201h mov dword [ebp-010h+04h],080402010h ; Line 42: key[2] = 0xf8fcfeff; key[3] = 0x80c0e0f0; mov dword [ebp-010h+08h],0f8fcfeffh mov dword [ebp-010h+0ch],080c0e0f0h ; Line 43: if (xxtea_encrypt(0x80c0e0f0f8fcfeff, key) != OUT1) { lea eax,[ebp-010h] push eax mov eax,0f8fcfeffh mov edx,080c0e0f0h push edx push eax call @xxtea_encrypt.qxuLpxui ; xxtea_encrypt( const unsigned long long, unsigned int const *) add esp,byte 0ch cmp edx,byte 0ffffffffh jne L_52 cmp eax,0c007378ch je L_39 L_52: ; Line 44: fprintf(stderr, "0: %llX %llX", xxtea_encrypt(0x80c0e0f0f8fcfeff, key), OUT1); push dword 0ffffffffh push dword 0c007378ch lea eax,[ebp-010h] push eax mov eax,0f8fcfeffh mov edx,080c0e0f0h push edx push eax call @xxtea_encrypt.qxuLpxui ; xxtea_encrypt( const unsigned long long, unsigned int const *) add esp,byte 0ch push edx push eax push dword L_1 mov eax,dword [___stderr] push eax call _fprintf ; fprintf add esp,byte 018h ; Line 45: return 0; xor eax,eax jmp L_30 On Tue, Nov 19, 2024 at 7:31 AM alvoskov ***@***.***> wrote: > The next XXTEA implementation gives incorrect result when compiled by OCC > 6.0.73. > Compilation in MinGW (both 32-bit and 64-bit), Open Watcom and Pelles C > gives correct results. > > The program output in OCC: > > Test result: 0 > 0: C4CC7F1CC007378C FFFFFFFFC007378C > > The source code: > > #include < stdio.h> > #include < stdlib.h> > #include < stdint.h> > > > #define MX(p) (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[((p)&3)^e] ^ z))) > > uint64_t xxtea_encrypt(const uint64_t inp, const uint32_t *key) > { > static const uint32_t DELTA = 0x9e3779b9; > static const unsigned int nrounds = 32; > uint32_t y, z, sum = 0; > union { > uint32_t v[2]; > uint64_t x; > } out; > out.x = inp; > z = out.v[1]; > for (unsigned int i = 0; i < nrounds; i++) { > sum += DELTA; > unsigned int e = (sum >> 2) & 3; > y = out.v[1]; > z = out.v[0] += MX(0); > y = out.v[0]; > z = out.v[1] += MX(1); > } > return out.x; > } > > int xxtea_test() > { > static const uint64_t OUT0 = 0x575d8c80053704ab; > static const uint64_t OUT1 = 0xc4cc7f1cc007378c; > uint32_t key[4] = {0, 0, 0, 0}; > // Test 1 > if (xxtea_encrypt(0, key) != OUT0) { > fprintf(stderr, "0: %llX %llX", xxtea_encrypt(0, key), OUT0); > return 0; > } > // Test 2 > key[0] = 0x08040201; key[1] = 0x80402010; > key[2] = 0xf8fcfeff; key[3] = 0x80c0e0f0; > if (xxtea_encrypt(0x80c0e0f0f8fcfeff, key) != OUT1) { > fprintf(stderr, "0: %llX %llX", xxtea_encrypt(0x80c0e0f0f8fcfeff, key), OUT1); > return 0; > } > return 1; > } > > int main() > { > printf("Test result: %d\n", xxtea_test()); > } > > — > Reply to this email directly, view it on GitHub > , or unsubscribe > > . > You are receiving this because you are subscribed to this thread.Message > ID: ***@***.***> >