clang/gcc是否优化了密码变量清除功能

clang/gcc是否优化了密码变量清除功能,c,gcc,clang,C,Gcc,Clang,我们担心恶意程序会试图从RAM中读取密码。因此,我们编写了一个函数来覆盖密码变量,然后释放它。我们担心的是,像clang或gcc这样的智能编译器会优化此函数中的代码。函数将字符串中的每个字符更改为空字节,然后释放变量 void free_pword(char* pword) { char* pword_original = pword; char c; while ((c = *(pword++))) { *pword = '\0'; }

我们担心恶意程序会试图从RAM中读取密码。因此,我们编写了一个函数来覆盖密码变量,然后释放它。我们担心的是,像clang或gcc这样的智能编译器会优化此函数中的代码。函数将字符串中的每个字符更改为空字节,然后释放变量

void free_pword(char* pword) {
    char* pword_original = pword;
    char c;

    while ((c = *(pword++))) {
        *pword = '\0';
    }

    free(pword_original);
}
现在是我们的问题。我们需要这样做吗?若否,原因为何?如果我们确实需要这样做,如何确保覆盖不会被优化

###########编辑1:(2015年2月11日) 亲爱的来自未来的人们:这是我们迄今为止所发现的

我查看了原始汇编代码(来自gcc),以确定代码是否经过了优化,而不是。我决定添加volatile,以防优化器在更新中发生更改

测试了gcc的版本

$ gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
我没有做出并接受我自己的答案,因为我不是100%确定这对所有编译器都是安全的。编译器专家可能能够肯定地回答

如果您需要像释放前一样安全地删除密码,请使用编译器测试此函数,并查看原始程序集。您不必理解程序集,只需确保调用了uuuubzero函数(memset)和free函数即可

当前工作版本:

void free_pword(char * pword) {
    //instead of changing the argument to the function, I added a volatile variable
    //this was I don't have to change the calls to this function to remove warnings
    char volatile * volatile_pword = pword;
    memset((char *)volatile_pword, 0, strlen((char *)volatile_pword));
    free((char *)volatile_pword);
}

编译器完全有可能优化对
memset
的调用。这就是为什么有像
memset_s
(C11)和
explicit_bzero
(BSD)这样的函数来安全地擦除内存块

我还认为使用volatile函数指针比将指针强制转换为volatile更可靠:

void *(*volatile forced_memset)(void *, int, size_t) = memset;

更多技巧,如插入
asm
语句或内存障碍,可以在这里找到。在这里,您还可以找到一个指向这一点的指针。

针对优化,首先想到的是
volatile
。如果你在一个单独的翻译单元中调用一个函数来执行密码的转换,编译器需要更多的时间来发现这个函数可能被删除。使用
memset()
或显示的代码可能会导致优化器忽略转换代码。顺便说一句,原始代码有一个错误-它不会覆盖密码中的第一个字符
pword
已按时间递增
*pword='\0'执行。