4

Cでのスタックスマッシングに関する知識が不足していることを事前に謝罪します。Code::Blocksを使用してubuntu12.04を編集しています。私はスタックスマッシングを引き起こす単純なCプログラムを作成しましたが、インターネット検索では、なぜこれが発生しているのかについての有用なアドバイスはほとんど見つかりませんでした。

Cコードの例:

#include<stdio.h>

struct point3
    {float x, y, z;};

struct quadPolygon
    {struct point3 vert1, vert2, vert3, vert4;};

int writeLine(const char * objString)
    {FILE *file; file = fopen("aPlane.obj","a+"); fprintf(file,"%s",objString); fclose(file); return 0;};

int writeOBJ(struct quadPolygon myPoly)
    {
    char objString[] = "# plane def\n";  writeLine(objString);

    snprintf(objString, 128, "v %f %f %f \n", myPoly.vert1.x, myPoly.vert1.y, myPoly.vert1.z);  writeLine(objString);
    snprintf(objString, 128, "v %f %f %f \n", myPoly.vert2.x, myPoly.vert2.y, myPoly.vert2.z);  writeLine(objString);
    snprintf(objString, 128, "v %f %f %f \n", myPoly.vert3.x, myPoly.vert3.y, myPoly.vert3.z);  writeLine(objString);
    snprintf(objString, 128, "v %f %f %f \n", myPoly.vert4.x, myPoly.vert4.y, myPoly.vert4.z);  writeLine(objString);

    char objStringSmooth[] = "s off\n";  writeLine(objStringSmooth);
    char objStringFace[] = "f 1 2 3 4\n";  writeLine(objStringFace);
    return 0;
    };

int main()
{
    struct quadPolygon myPoly1 =
    {
    .vert1.x=1.0, .vert1.y=-1.0, .vert1.z=0.0,
    .vert2.x=1.0, .vert2.y=1.0, .vert2.z=0.0,
    .vert3.x=-1.0, .vert3.y=1.0, .vert3.z=0.0,
    .vert4.x=-1.0, .vert4.y=-1.0, .vert4.z=0.0
    };
    writeOBJ(myPoly1);
    return 0;
};

スタックが壊れるのはなぜですか?これを回避するためにコードを変更するにはどうすればよいですか?これは、上記のコードでポインターを誤って使用することに関連していますか?おそらくお分かりのように、私はCに少し慣れていませんが、他の言語でのプログラミング経験はあります。

「スタックスマッシングは、実際にはgccがバッファオーバーフロー攻撃を検出するために使用する保護メカニズムです」と「これは、おそらくバッファオーバーフローの結果として、スタック上のいくつかの変数に不正な方法で書き込んだことを意味します」と読みました。

回答・回答ありがとうございます。

更新 -Evanのコメントに基づいて、動作する改訂されたコードがあります。おそらくこれは他の誰かを助けるかもしれません。

#include<stdio.h>

struct point3
    {float x, y, z;};

struct quadPolygon
    {struct point3 vert1, vert2, vert3, vert4;};

int writeOBJ(struct quadPolygon myPoly)
    {
    FILE *file; file = fopen("aPlane.obj","a+");
    fprintf(file,"%s","# plane def\n");
    char objString[128];
    snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert1.x, myPoly.vert1.y, myPoly.vert1.z);
        fprintf(file,"%s",objString);
    snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert2.x, myPoly.vert2.y, myPoly.vert2.z);
        fprintf(file,"%s",objString);
    snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert3.x, myPoly.vert3.y, myPoly.vert3.z);
        fprintf(file,"%s",objString);
    snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert4.x, myPoly.vert4.y, myPoly.vert4.z);
        fprintf(file,"%s",objString);
    char objStringSmooth[] = "s off\n";
        fprintf(file,"%s",objStringSmooth);
    char objStringFace[] = "f 1 2 3 4\n";
        fprintf(file,"%s",objStringFace);
    fclose(file);
    return 0;
    };

int main()
    {
    struct quadPolygon myPoly1 =
        {
        .vert1.x=1.0, .vert1.y=-1.0, .vert1.z=0.0,
        .vert2.x=1.0, .vert2.y=1.0, .vert2.z=0.0,
        .vert3.x=-1.0, .vert3.y=1.0, .vert3.z=0.0,
        .vert4.x=-1.0, .vert4.y=-1.0, .vert4.z=0.0
        };

    writeOBJ(myPoly1);
    return 0;
    };

みなさん、ありがとうございました。

4

4 に答える 4

6

これがあなたの問題です:

char objString[] = "# plane def\n";  writeLine(objString);

snprintf(objString, 128, "v %f %f %f \n", myPoly.vert1.x, myPoly.vert1.y, myPoly.vert1.z);  writeLine(objString);
snprintf(objString, 128, "v %f %f %f \n", myPoly.vert2.x, myPoly.vert2.y, myPoly.vert2.z);  writeLine(objString);
snprintf(objString, 128, "v %f %f %f \n", myPoly.vert3.x, myPoly.vert3.y, myPoly.vert3.z);  writeLine(objString);
snprintf(objString, 128, "v %f %f %f \n", myPoly.vert4.x, myPoly.vert4.y, myPoly.vert4.z);  writeLine(objString);

objStringstrlen("# plane def\n") + 1スペースの文字を含む配列です。次にsnprintf、そのバッファパスで使用します128(これは大きすぎます)。

私はそれをこのように書き直します:

writeLine("# plane def\n");

char objString[128]
snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert1.x, myPoly.vert1.y, myPoly.vert1.z);  writeLine(objString);
snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert2.x, myPoly.vert2.y, myPoly.vert2.z);  writeLine(objString);
snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert3.x, myPoly.vert3.y, myPoly.vert3.z);  writeLine(objString);
snprintf(objString, sizeof(objString), "v %f %f %f \n", myPoly.vert4.x, myPoly.vert4.y, myPoly.vert4.z);  writeLine(objString);

サイドポイント:

書き込まれるすべての行のファイルを開いたり閉じたりするのはなぜですか?それは信じられないほど非効率的です...

プログラムの開始時にファイルを1回開き、すべての行を書き込み、終了したらファイルを閉じる方がよいでしょう。これにより、コードも簡単になります。

于 2012-05-25T00:26:04.203 に答える
0

FILE*有効なものを取得していることを確認できますfopen

NULLポインタの明示的なチェックによる。

于 2012-05-25T00:30:02.463 に答える
0

問題は次の行にあります。

char objString[] = "# plane def\n";

これは、文字列 "#plane def \ n"に十分なスペースを割り当てるだけで、後で(snprintfを使用して)より長い文字列を書き込みます。

すでに定数値128を使用しているので、どうでしょうか。

char objString[128];
strcpy(objString, "# plane def\n");
writeLine(objString);
/* continue as before */

strcpyもスタックを壊す可能性があることに注意してください。そのため、コピー先にコピーするものすべてに十分なスペースがあることを確認してください。

于 2012-05-25T00:30:53.403 に答える
0

それはすでにエヴァンテランによって答えられているように。しかし、私はそのような問題を検出するためのいくつかの方法を提案したいと思います:

  • を使用してコンパイルしてみてgcc -fno-stack-protector stack.c、それでもが得られるかどうかを確認してくださいstack smash detected
  • -ggnu-debuggerにはフラグを使用します。としてgcc -g stack.c- gdb a.out> run。問題が発生したところで実行を停止します。次にwhere、gdbと入力して、問題の原因となっているコード行を確認できます。
于 2012-05-25T00:34:27.627 に答える