-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Description
| Bugzilla Link | 4210 |
| Resolution | FIXED |
| Resolved on | May 15, 2009 05:30 |
| Version | unspecified |
| OS | MacOS X |
| Attachments | standalone test case |
| Reporter | LLVM Bugzilla Contributor |
| CC | @asl,@sunfishcode,@nlewycky |
Extended Description
When building MySQL 5.0 with clang (at least for a Mac OS X x86_64 target), turning on optimisation (-O1 or above) breaks AES encryption/decryption functionality as compared to a build without optimisation (-O0).
The attached standalone test case was extracted from the MySQL 5.0 code base. I'm sorry that it is still quite large, I've not had much luck with extracting the individual bit that is optimised badly, but I have reduced it to one code path in one function that shows the problem.
To compile:
clang -o rijndael_test_O0 rijndael_bug.c -O0
clang -o rijndael_test_O1 rijndael_bug.c -O0
clang -o rijndael_test_O1V rijndael_bug.c -O0 -DVOLATILE=volatile
The output of rijndael_test_O0 is as follows:
39 25 cc 14 d7 5 ef 4e e9 c7 fb cd 40 22 ed 29
The output of rijndael_test_O1 is as follows:
39 25 cc 14 d7 5 ef 4e e9 c7 fb d1 40 22 ed 29
Note that the 12th byte is different.
The output of rijndael_test_O1V is the same as rijndael_test_O0:
39 25 cc 14 d7 5 ef 4e e9 c7 fb cd 40 22 ed 29
The difference between O1 and O1V is that a "volatile" statement is added to the variable declaration in the rijndaelEncrypt function. In fact it seems to be sufficient to declare one of these variables volatile to make the problem go away.
I have inserted one comment into the source:
/* Value of t1 will be different depending on optimisation */
At this location, a value t1 is computed as follows:
t1= (Te0[(s1 >> 24) ] ^
Te1[(s2 >> 16) & 0xff] ^
Te2[(s3 >> 8) & 0xff] ^
Te3[(s0 ) & 0xff] ^
rk[5]);
The result of this calculation is different when optimisation is turned on. I wasn't able to reproduce this with the snippet on its own.
The full version of the rijndaelEncrypt function in the MySQL code base has an alternate code path that can be enabled with -DFULL_UNROLL. I removed this codepath from the test case because it does not exhibit the problem.