10

RtlSecureZeroMemoryメモリのブロックをゼロにする関数である/に相当するMacOSXはあり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)man ページ には、オプティマイザによる削除の対象ではないとは記載されていません。

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 に答える