我只是想知道,因为我有这个C代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int fillBuffer(int argc, char *argv[]) {
char bufferA[4] = "aaa";
char bufferB[4] = "bbb";
if(argc > 1)
strcpy(bufferB, argv[1]);
printf("bufferA: %s\n", bufferA);
printf("bufferB: %s\n", bufferB);
return 0;
}
int main(int argc, char *argv[]) {
fillBuffer(argc, argv);
return 0;
}
我尝试使用:-fno-stack-protector
关闭堆栈保护当我尝试运行它:./ program(escape key)5f时,程序输出到:
bufferA:f
bufferB:fffff
我只是不确定bufferA是如何成为f的。任何人都可以向我解释这个吗?
答案 0 :(得分:1)
本地缓冲区A和B以相反的顺序存储在堆栈中。因此,在内存中,您有8个字节,启动缓冲区B,然后是缓冲区A.
当你敲打你的5&#34; f&#34;缓冲B,前4个进入缓冲区B,最后一个结束字符串&#39; \ 0&#39;缓冲A。
然后当你打印缓冲区时,缓冲区A包含1&#34; f&#34;和字符串终止符。它来自哪里。
答案 1 :(得分:0)
你的strcpy调用是不安全的,如果argv [1]包含超过3个字符(加上一个空终止字符),它将损坏你的堆栈。不要逃脱,只是空间和5f,你得到正确的输出:
scott> a.out 5f
bufferA: aaa
bufferB: 5f
当你点击转义时,shell可以在字符串参数中添加其他字符,并且由于你的strcpy不安全(不检查长度),它将超出缓冲区的末尾并破坏你的堆栈。您的缓冲区只有4个字符长,因此如果输入的参数超过3个字符,您的程序将损坏堆栈。
要修复它,请将缓冲区大小从4增加到更合理的值(如60),如果参数太长,请使用strncpy确保不超过缓冲区:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_PARM_LEN 60
int fillBuffer(int argc, char *argv[]) {
char bufferA[MAX_PARM_LEN] = "aaa";
char bufferB[MAX_PARM_LEN] = "bbb";
if(argc > 1)
strncpy(bufferB, argv[1], MAX_PARM_LEN);
printf("bufferA: %s\n", bufferA);
printf("bufferB: %s\n", bufferB);
return 0;
}
int main(int argc, char *argv[]) {
fillBuffer(argc, argv);
return 0;
}
最后一点:不要关闭堆栈保护。