I implemented (read: copy & pasted from wiki ) the XXTEA cipher into a C ++ project. For clarity, I shared encryption and decryption in separate functions: (NOTE: this is not a cryptographic question! Please do not comment on the selected cipher)
#define DELTA 0x9e3779b9 #define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z))) static void btea_enc( unsigned int *v, unsigned n, const unsigned int* key ) { unsigned int y, z, sum; unsigned p, rounds, e; rounds = 16 + 52/n; sum = 0; z = v[n-1]; do { sum += DELTA; e = (sum >> 2) & 3; for (p=0; p<n-1; p++) { y = v[p+1]; z = v[p] += MX; } y = v[0]; z = v[n-1] += MX; } while (--rounds); } static void btea_dec( unsigned int *v, unsigned n, const unsigned int* key ) { unsigned int y, z, sum; unsigned p, rounds, e; rounds = 16 + 52/n; sum = rounds*DELTA; y = v[0]; do { e = (sum >> 2) & 3; for (p=n-1; p>0; p--) { z = v[p-1]; y = v[p] -= MX; } z = v[n-1]; y = v[0] -= MX; } while ((sum -= DELTA) != 0); } #undef MX #undef DELTA
When this code is compiled into Debug, it works great. However, when I compile this code with (by default) optimization using Visual Studio 2013 (v120), btea_dec loses its outer loop (causing decryption to create garbage).
Collapsible encryption listing and decryption . Note the missing outer loop during decryption! (if you want the code to be text, I would be happy to download it, it's just a wall with text)
Looking at the actual code, the final condition is an overflowing unsigned int 'sum':
while ((sum -= DELTA) != 0)
I donβt understand what the compiler did to make him think that he can get rid of this loop (afaik overflow is only undefined for integers, unsigned overflow is fine).
Question: Why does the compiler "optimize" the outer contour? And how to fix it?
MCVE: (insert the previous code block containing btea_enc and btea_dec between include and main)
#define _CRT_RAND_S #include <cstdlib> int main(int argc, char* argv[]) { // Random key unsigned int key[4]; rand_s(&key[0]); rand_s(&key[1]); rand_s(&key[2]); rand_s(&key[3]); // Buffer we'll be encrypting unsigned int utext[4]; memcpy(utext, "SecretPlaintext", 16); // Encrypt btea_enc(utext, 4, key); // Decrypt btea_dec(utext, 4, key); // Should still be equal! bool s = !strcmp((char*)utext, "SecretPlaintext"); // Print message printf("Compared: %s\n", s ? "equal" : "falsly"); return s?0:1; }