私の(ココア)-Xcode内から起動すると、アプリは完全に正常に動作します。ただし、アーカイブ/リリースすると、そのバージョンがクラッシュします。開いたエラーレポーターは次のように述べています。
[...]
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Application Specific Information:
[9082] stack overflow
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x00007fff944a7212 __pthread_kill + 10
1 libsystem_c.dylib 0x00007fff9290caf4 pthread_kill + 90
2 libsystem_c.dylib 0x00007fff92950e9e __abort + 159
3 libsystem_c.dylib 0x00007fff92951d17 __stack_chk_fail + 195
[...]
また、実行が停止したコード行も表示されますが、まったく同じコードパスがデバッグモードで実行されるため(ただし成功するため)、これは実際には役に立ちません。
だから私は疑問に思っています:実際には、リリースとデバッグバージョンでスタックサイズが異なるのでしょうか?そして、結局のところMac(64ビット/ Mountain Lion)のスタックはどれくらいの大きさですか?スタックにめちゃくちゃ多くのデータを入れていることに気づいていません...
スタックにデータが多すぎる場合、スタックの負荷を減らすためにどのようなパターンを避ける必要がありますか?
[アップデート]
わかりました-fno-stack-protector
。フラグを追加してアプリを実行しました。(ところで:私はLLVMでコンパイルしています)
その前に、クラッシュするコードを1行ずつ調べてみたところ、理解できない次の動作が見つかりました。メソッドは。をfoo(x)
呼び出しますbacon(x)
。x
は8で、変更なしでからfoo
に渡されbacon
ます。しかし、私が足を踏み入れるとbacon(x)
、x
突然4295939448になります(毎回)。私が設定した場合-fno-stack-protector
、値は正しいです。
私の素朴な目には、これはスタックプロテクターがスタックのどこかに魔法の値4295939448を設定し、それを読み取り専用にするように見えます。そして、私の関数はパラメーターをスタックに置きますが、ある時点でパラメーターx
がその魔法のアドレスに置かれるため、書き込むことができません(後続のパラメーターは正しく書き込まれているようです)。私の場合x
はバッファ長パラメータであり、これは当然バッファオーバーフローとクラッシュにつながります。
誰かがスタックプロテクターをより深く理解していますか?なぜこうなった?また、スタックプロテクターを無効にすることはどのような場合に安全かつ合法であり、どのような場合に危険ですか?
[更新2:元のコード]
このメソッドは、Decrypt
以下の他のメソッドを呼び出します。その時点でのstIVLenは8です
BOOL CEracomSE::Decrypt(
PBYTE pMsg, size_t stLen,
const CSK* pKey /* = NULL */,
PBYTE pIV /* = NULL */, size_t stIVLen /* = 0 */,
FBM fbm /* = FBM_CBC */,
PADDING padding /* = NO_PADDING */
)
{
//stIVLen == 8
return Decrypt( (uint64_t)0, pMsg, stLen, pKey, pIV, stIVLen, fbm, padding );
}
Decrypt
stIVLenが4295939448と呼ばれる場合、他のパラメーターは引き続き正しい
BOOL CEracomSE::Decrypt(
uint64_t qwOffset,
PBYTE pMsg, size_t stLen,
const CSK* pKey /* = NULL */,
PBYTE pIV /* = NULL */, size_t stIVLen /* = 0 */,
FBM fbm /* = FBM_CBC */,
PADDING padding /* = NO_PADDING */
)
{
//stIVLen now is 4295939448
BYTE a_iv[16] = {0};
size_t a_iv_len;
BYTE a_key[32] = {0};
size_t a_key_len = 0;
size_t nBytes;
size_t nDataOffset;
size_t nRemainingData = stLen;
bool ret;
//[...]
}