[解決済み] malloc():先頭のサイズが壊れている
質問
ファイル内のテキスト行を復号化するプログラムを作成しています。まず、私が作成した別のソースコードが、シフトといくつかのテキストを要求します。ソースコードはテキストを暗号化し、それをファイルに書き込む。
次に、指定されたファイルを以下のコード-別のソースコード-で復号化してみる。ファイル名が取得される。ファイル名から、shiftを取得する。ファイル内に書かれているすべての文字をコピーし、shiftの値だけシフトさせる。ただし、与えられた文字は、32から127の間のascii値でなければ、32から127の間の別の文字に変換されません。
剰余演算子(正の数のモジュロ)と負の数のモジュロをカプセル化したモジュロ関数を定義しました。また、pythonのstrip関数と同じように動作するstrip関数も定義した。この関数では、空白以外のすべてのリテラルを削除する。また、pythonのinput()に相当するgetIn()も用意しました。
印刷したり、gdbでデバッグを試みました。有効な結果が得られません。私はstackoverflowでこのトピックについて調査しました。1つのエントリを見つけました。回答は、私の特定の問題を扱っていませんでした。
注:必要な詳細情報が必要だと思ったので、プログラム全体をコピーしました。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
/*GETIN FUNCTION*/
char* getIn()
{
char *line = NULL, *tmp = NULL;
size_t size = 0, index = 0;
int ch = EOF;
while (ch)
{
ch = getc(stdin);
/* Check if we need to stop. */
if (ch == EOF || ch == '\n')
ch = 0;
/* Check if we need to expand. */
if (size <= index)
{
size += sizeof(char);
tmp = realloc(line, size);
if (!tmp)
{
free(line);
line = NULL;
break;
}
line = tmp;
}
/* Actually store the thing. */
line[index++] = ch;
}
return line;
}
/*FUNCTION THAT CONVERTS TO NUMERIC CHARACTER, PRECURSOR OF DIGITS OF SHIFT*/
char make_numeric(char ch)
{
if(ch<91 && ch>63) return ch-16;
if(ch<123 && ch>95) return ch-48;
if(ch<58 && ch>47) return ch;
return ch+16;
}
/*STRIP FUNCTION*/
char* strip(char* str,int length)
{
char *start=str,*end=&str[length-1];
while(*start>0 && *start<33 || *start==127) ++start;
if(!*start) return start;
while(*end>=0 && *end<33 || *end==127) --end;
++end;
*end=0;
return start;
}
/*DECRYPTOR FUNCTION*/
char *caesar_decrypt(char *message_to_decrypt, void *shift)
{
int length=strlen(message_to_decrypt),i;
char* decrypted_message;
if(!message_to_decrypt) return NULL;
if(!(decrypted_message=calloc(length+1,sizeof(char)))) return NULL;
for(i=0;i<length;++i)
{
decrypted_message[i]=mod((message_to_decrypt[i]-33-*((int*)shift)),94)+33;
}
return decrypted_message;
}
/*THE MAIN PROGRAM*/
int main()
{
int shift,len_chshift,init,len_filename,i=0;
char *chshift,*line=NULL,*decrypted_line,*stripped_line,chinit,chlen_chshift;
char *filename=NULL,*newfilename=NULL;
FILE *oldfile=NULL;
FILE *newfile=NULL;
size_t lenline,len=0;
printf("-9");
/*FILENAME*/
printf("Enter the file name: ");
/*printf("-8");*/
filename=getIn();
/*printf("-7");*/
if(!access(filename,F_OK))
{
len_filename=strlen(filename);
/*printf("-6");*/
i=len_filename;
while(filename[i]!='.') --i;
chlen_chshift=filename[i-1];
chlen_chshift=make_numeric(chlen_chshift);
len_chshift=chlen_chshift-48;
/*printf("-5");*/
chshift=calloc(len_chshift+1,1);
/*NEWFILENAME*/
newfilename=calloc(i+1,1);
/*printf("-4");*/
strncpy(newfilename,filename,i);
/*printf("-3");*/
strcat(newfilename,"(decrypted).txt");
/*printf("-2");*/
chinit=make_numeric(filename[0]);
init=chinit-48;
/*SHIFT*/
i=0;
/*printf("-1");*/
while(i!=len_chshift)
{
chshift[i]=make_numeric(filename[(i+1)*init]);
++i;
}
/*printf("0");*/
shift=atoi(chshift);
/*printf("1");*/
if(!(oldfile=fopen(filename,"r")))
{
perror("Error");
if(newfilename) free(newfilename);
if(filename) free(filename);
if(chshift) free(chshift);
exit(1);
}
/*printf("2");*/
if(!(newfile=fopen(newfilename,"+ab")))
{
perror("Error");
if(newfilename) free(newfilename);
if(filename) free(filename);
if(chshift) free(chshift);
fclose(oldfile);
exit(1);
}
while ((lenline = getline(&line, &len, oldfile)) != -1)
{
stripped_line=strip(line,lenline);
decrypted_line=caesar_decrypt(stripped_line, &shift);
if(!decrypted_line)
{
printf("Could not allocate memory\n");
if(newfilename) free(newfilename);
if(filename) free(filename);
if(chshift) free(chshift);
exit(1);
}
fprintf(newfile,"%s\n",decrypted_line);
if(decrypted_line) free(decrypted_line);
decrypted_line=NULL;
free(line);
line=NULL;
stripped_line=NULL;
decrypted_line=NULL;
}
free(line);
line=NULL;
}
else
{
printf("Cannot access the file.");
if(filename) free(filename);
exit(0);
}
if(newfilename) free(newfilename);
if(filename) free(filename);
if(chshift) free(chshift);
fclose(oldfile);
fclose(newfile);
return 0;
}
このプログラムはファイルを作成する必要があり、そのファイルのコンテキストは、ユーザが最初に提供したファイル名のクローンを復号化したものである。しかし、最初のfopenの直前で投げられてしまいます。
malloc(): corrupted top size
Aborted (core dumped)
printfの行をすべてアンコメントすると、getIn()とprintf("-7");の行の間で同じエラーになります。printfsをコメントアウトすると、filenameにはgetIn()で返された値が書き込まれていることが確認できます。従って、getIn()は問題ないと思います。
EDIT(1) : 不足していたヘッダを2つ追加しましたが、まだ同じエラーが発生します。
EDIT(2) : 不要なヘッダを全て削除しました。
EDIT(3) : ご要望がありましたので、例で説明します。という名前のファイルがあるとします。
2/b*A".txt
2行のコードで
%52
abcd
プログラムにファイル名を入力します。
1)最後の文字が . は " に変換され、数値に変換されます。 2 . シフトは2桁の数字であることがわかります。
2)最初の文字はイニシエータで、これは 2 は、繰り返しジャンプする必要のある文字数です。シフト番号が2桁なので、2文字を2回ジャンプさせます。
3)今、bとAはそれぞれ2と1に変換されています。シフトは21です。最初の文字 % (37)を逆シフトさせ n (110)といった内容のファイルを新規に作成する必要があります。
n~#
LMNO
よろしくお願いします。よろしくお願いします。なお、私が述べた変数は、特定の間隔にある任意の文字です。詳しくはソースコードをご覧いただくか、プログラム全体をお渡ししていますので、ローカルで作業されることをお勧めします。
アスキーコードの場合 https://www.asciitable.com/
カエサルの暗号に興味がある方 https://en.wikipedia.org/wiki/Caesar_cipher
解決方法は?
でバッファオーバーフローが発生しています。
newfilename
:
/* here you declare that the string pointed to by newfilename may contain `i`
chars + zero-termination...*/
newfilename=calloc(i+1,1);
/* Here `i` is less than `strlen(filename)`, so only i characters from `filename`
will be copied, that does NOT include the zero-termination
(but it will be zero-terminated because the last byte in the buffer was
already cleared by `calloc`) */
strncpy(newfilename,filename,i);
/* Here `newfilename` is full, and `strcat` will write outside buffer!! Whatever
happens after this line is undefined behaviour */
strcat(newfilename,"(decrypted).txt");
のために十分なスペースを確保しなければならないわけです。
newfilename
:
newfilename = calloc (i + strlen("(decrypted).txt") + 1, 1);
関連
-
[解決済み】エラー:cの入力の最後に期待される宣言またはステートメント
-
[解決済み】 `S_ISREG()` とは何ですか、そして何をするのですか?
-
[解決済み] strtokのセグメンテーションフォールト
-
[解決済み】 「配列のイニシャライザーはイニシャライザーリストまたは文字列リテラルでなければなりません」と表示されるのですが?
-
[解決済み] mallocの結果はキャストするのですか?
-
[解決済み] C言語で配列のサイズを決定するにはどうすればよいですか?
-
[解決済み] mallocとcallocの違い?
-
[解決済み] プログラム終了前にmallocの後にfreeをしないと本当に何が起こるのか?
-
[解決済み】malloc()とfree()はどのように動作するのですか?
-
[解決済み】malloc+memsetはcallocより遅いのはなぜ?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Cコンパイルエラー。"変数サイズのオブジェクトが初期化されていない可能性がある"
-
[解決済み] c - 初期化がキャストなしでポインタから整数を作る、さらに2つのコンパイラーエラー
-
[解決済み] strtokのセグメンテーションフォールト
-
[解決済み】C言語におけるファイルスコープでの可変長配列の変更
-
[解決済み】ポインタと整数の比較で警告が出る
-
[解決済み】LEALアセンブリ命令は何をするのですか?
-
[解決済み】ヒープ割り当てで初期化されていない値が作成された
-
[解決済み】argv[]をint型として取得するには?
-
[解決済み】シンプルなC言語のscanfが機能しない?重複
-
[解決済み】whileループの時間複雑性(Big O)はどうやったらわかるの?