-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 (My PGP client botched the signature last time when I used the clipboard method. This time I'm using the plugin button and it should work. Stupid GUI crap.)
I have devised what I believe to be a foolproof and completely portable way of setting an array of bytes to all zeroes, a common security operation in cryptography programs. void clear_bytes(char magic, char p[], int n) { int i; p[0] &= magic; for (i = 1; i < n; i++) p[i] &= p[i-1]; for (i = 0; i < n; i++) if (p[i] != magic) exit(magic); } In order to guarantee that this works, you must pass in 0 as the value of the 'magic' parameter, and you also must establish that 0 value using a method that is completely undecidable even to the most intelligent compiler optimizer theoretically possible. Here is a simple example of how we can generate this "undecidable zero" and pass it into the routine. int main(int argc, char *argv[]) { char array[32]; char magic = (argc < 1 ? 0 : 255); clear_bytes(magic, array, sizeof(array)); return 0; } If you call this program with no command line arguments, the value of magic will be 0 and the clear_bytes is guaranteed to zero out the array. If you call this program with any command line arguments at all, the value of magic will be 255 and the clear_bytes routine will exit with code 255. So the clear_bytes routine serves a dual purpose as an assertion that the clearing operation actually occurs properly. If it doesn't, your program aborts. It is impossible for a compiler to optimize away any of this code, because you can always find a way from OUTSIDE the program to make magic take on a nonzero value and thus reach the abort condition. Of course, your program will very likely expect command line arguments, but you can use a slightly altered technique for generating the necessary "magic undecidable zero." For example, if you know that your program will never be called with more than 5 arguments, just use this line: char magic = (argc < 6 ? 0 : 255); In the very worst case the number of arguments to your program will be totally indeterminate, with no theoretical upper bound. This could easily happen if you expect file names with shell expansion, for example. In this case, you could simply require that the very first argument to your program must always be a specific character, for example 't'. char magic = ((argc > 1 && argv[1][0] == 't') ? 0 : 255); With this line, if the first argument to the program starts with a 't', magic will take on the correct value of 0. I do not recommend using anything in argv[0] because that is the actual name of your program as invoked from the command line. This could change if the executable file is renamed or if you call it with a leading path. You can always find some way to generate a magic undecidable zero. Some variation of the argc/argv technique should serve you well in all reasonable circumstances, but if you absolutely had to you could read a zero byte out of a file somewhere. Note that the clear_bytes function 'ands' each byte of the array with the previous byte, starting with the magic value. Only a magic value of 0 is guaranteed to make all the bytes zero. The second loop then checks the operation, ensuring that each byte is equal to the magic byte. This can only succeed if magic is 0 and all the bytes are 0. (Actually it could succeed with a nonzero magic value, but only if all the bytes were already equal to magic to begin with. Obviously this case is irrelevant.) So folks, this routine will definitely zero out an array, and it doesn't rely on the va_list (vararg) technique described in Welschenbach's book. Personally I rarely use global variables, so I like to pass the magic value around as an explicit parameter wherever it is needed. But you could use a global magic variable if you preferred. - - -- Patrick http://fexl.com -----BEGIN PGP SIGNATURE----- Version: PGP 8.0 iQA/AwUBPl71Y1A7g7bodUwLEQKoywCgg50VenX0boJAeIxrNIYI9KAmhR0AoOvJ XByLpkEtgt9QhFbmiHokzC3V =ZLC3 -----END PGP SIGNATURE-----