我遇到了一些我发现的问题。鉴于以下内容:
int match(char *s1, char *s2) {
while( *s1 != '\0' && *s2 != '\0' && *s1 == *s2 ){
s1++; s2++;
}
return( *s1 - *s2 );
}
int main() {
char str1[8], str2[8];
scanf("%s", str1);
scanf("%s", str2);
if (match(str1, str2) == 0)
printf("They are the same.\n");
else
printf("They are not the same.\n");
}
可以使用两个不同值的输入字符串来使程序打印消息“它们是相同的”? (上面的代码不能更改)
据我所知,当数组被添加到堆栈中时,它们被“推入”它并且信息以相同的方向写入。因此,如果我输入“AAAAAAAAA”(A x 9)到str2,它将溢出并且str1将打印“A”。
我的第一次尝试是为str2输入A x 16,希望程序用8 A覆盖str1中的值,程序只读取str2中的8个值。 str1的值为A x 8,但str2的值保持为A x 16。
有没有办法用它来解决这个问题?或者我是否以错误的方式思考这个问题?
编辑:此问题意味着要在具有过时且易受攻击的Linux版本的特定计算机上运行。我通过gdb运行程序,它显示两个字符串在内存中彼此相邻,并且str2溢出到str1中。那么我的问题是,我可以使用它来使str2和str1在比较它们时看起来与程序相同吗?
答案 0 :(得分:3)
可以使用两个不同值的输入字符串来使程序打印消息“它们是相同的”? (上面的代码不能更改)
不存在这样明确定义的场景。这些要求毫无意义。
据我所知,当数组被添加到堆栈中时,它们被“推入”它并且信息以相同的方向写入。因此,如果我输入“AAAAAAAAA”(A x 9)到str2,它将溢出并且str1将打印“A”。
这是不正确的。缓冲区str1
(可以包含 7 字母+ 1个空终止)将溢出,并且从那里可能发生任何事情,您调用未定义的行为。可能的未定义行为的一些示例是:分段故障/崩溃&刻录,或程序似乎正常工作。
无法保证str2与str1相邻分配。也没有任何保证str1在str2之前分配。甚至没有任何保证它们在堆栈上分配,尽管这很可能。
有没有办法用它来解决这个问题?
没有
或者我是否以错误的方式思考这个问题?
是
答案 1 :(得分:2)
我有另一个想法:如果输入“A”和“A A”会怎样?根据{{3}},sscanf
期望'%s'的非空格字符,因此它将在“A A”中的第一个“A”之后停止读取(注意空格字符)。标签“缓冲区溢出”具有误导性。
答案 2 :(得分:1)
覆盖缓冲区会调用未定义的行为。任何事情都可能发生,所以你绝不能依赖它。
此外,str1
和str2
在内存中不一定是彼此相邻的,你不能依赖它。
可能的解决方案
char buffer[16];
char * str1 = &buffer[8];
char * str2 = &buffer[0];
这样您就可以安全地从str2
溢出到str1
(但不能从str1
溢出到str2
)。你应该仍然有适当的长度检查。
答案 3 :(得分:1)
你有没有试过相反的方法?这取决于堆栈的布局方式。我会为str2尝试“AAAAAAAAAA”forstr1和“AAAAAAA”(7x'A')。 AFAIR堆栈从上到下增长。
请参阅here以获取解释。
编辑:我知道如果你写过数组限制会发生邪恶(未定义)的事情,但问题明确告诉不要改变程序。看起来像是了解软件开发中的安全风险。答案 4 :(得分:0)
可以使用两个不同值的输入字符串来使程序打印消息“它们是相同的”?
您的字符串比较功能错误。 return( *s1 - *s2 );
在这里毫无意义。将功能更改为
int match(char *s1, char *s2) {
while( *s1 != '\0' && *s2 != '\0') {
if(*s1 != *s2 )
return 1;
s1++; s2++;
}
return 0;
}