10

是否有 Mac OS X 等效的RtlSecureZeroMemory/ SecureZeroMemory,一个将内存块归零的函数,但编译器不会优化调用?

4

2 回答 2

14

编写自己的函数:

void secure_zero(void *s, size_t n)
{
    volatile char *p = s;

    while (n--) *p++ = 0;
}

编辑:对于评论中的问题,为什么不memset呢?如果memset不再访问数组对象,则编译器可以优化函数调用。

请注意,C11 添加了(可选)函数memset_s,并且标准保证函数调用不能被优化掉:

(C11, K.3.7.4.1p4) “[...] 与 memset 不同,对 memset_s 函数的任何调用都应严格按照 (5.1.2.3) 中描述的抽象机规则进行评估。也就是说,任何对 memset_s 函数的调用应假定 s 和 n 指示的内存将来可以访问,因此必须包含 c 指示的值。”

于 2012-11-08T23:04:56.537 回答
4

是否有 RtlSecureZeroMemory / SecureZeroMemory 的 Mac OS X 等价物,一个将内存块归零的函数,但编译器不会优化调用?

在 C 运行时的更新版本中,您拥有memset_s. 它保证不会被优化掉。

#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
errno_t memset_s(void * restrict s, rsize_t smax, int c, rsize_t n)

OS X 也包含该bzero功能。但是bzero(3)手册页 没有说明它不会被优化器删除。

避免使用限定符的技巧,volatile因为它不可移植。它在 Windows 上按预期工作,但 GCC 人员将其解释volatile为由硬件支持的 I/O 内存。所以你不应该用来volatile驯服优化器。


这是您可以使用的内联汇编实现。奇怪的是,__volatile__在 ASM 语句和块上都可以。它在 OS X 上运行良好(这是最初编写的地方)。

// g++ -Og -g3 -m64 wipe.cpp -o wipe.exe
// g++ -Og -g3 -m32 wipe.cpp -o wipe.exe    
// g++ -Os -g2 -S -m64 wipe.cpp -o wipe.exe.S
// g++ -Os -g2 -S -m32 wipe.cpp -o wipe.exe.S

#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
    string s("Hello world");
    cout << "S: " << s << endl;

    char* ptr = &s[0];
    size_t size = s.length();

    if(ptr && size)
    {
        /* Needed because we can't just say to GCC, */
        /*   "give me a register that you choose".  */
        void* dummy;

        __asm__ __volatile__
        (
         "%=:\n\t"                /* generate a unique label for TOP */

#if (__WORDSIZE == 64)
         "subq $1, %2\n\t"        /* 0-based index */
#elif (__WORDSIZE == 32)
         "subl $1, %2\n\t"        /* 0-based index */
#elif (__WORDSIZE == 16)
         "subw $1, %2\n\t"        /* 0-based index */
#else
# error Unknown machine word size
#endif

         "lea (%1, %2), %0\n\t"   /* calcualte ptr[idx] */
         "movb $0, (%0)\n\t"      /* 0 -> ptr[size - 1] .. ptr[0] */
         "jnz %=b\n\t"            /* Back to TOP if non-zero */

         : "=&r" (dummy)
         :  "r" (ptr), "r" (size)
         : "0", "1", "2", "cc"
         );
    }

#if 0
    cout.setf(ios::hex, ios::basefield);
    cout.fill('0');

    for(size_t i = 0; i < s.length(); i++)
        cout << "0x" << setw(2) << ((int)s[i] & 0xff) << " ";

    cout << endl;
#endif

    cout << "S: " << s << endl;

    return 0;
}
于 2015-01-22T09:08:40.510 回答