向我解释以下C程序的输出

时间:2014-02-19 09:53:20

标签: c

请解释下面的例子。问题很简单,但结果很突然。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
  int flag = 0;
  char passwd[10];
  strcpy(passwd, argv[1]);
  if(0 == strcmp("LinuxGeek", passwd))
    {
      flag = 1;
    }

  if(flag)
    {
      printf("\n Password cracked \n");
    }
  else
    {
      printf("\n Incorrect passwd \n");

    }
  return 0;
} 

标志的值在行

之后变为垃圾值
strcpy(passwd, argv[1]);

但是,如果我将变量标志定义为

int flag = 0 
行后

strcpy(passwd, argv[1]);

我得到了理想的结果。请简要解释一下。

3 个答案:

答案 0 :(得分:6)

简短的回答是,当argv[1]的长度大于9时,程序的行为是未定义的,因为那样会溢出缓冲区passwd

很长的答案显然,你的编译器按照列出的顺序对堆栈中的变量进行排序,因此在flag之后移动passwd会在缓冲区和strcmp之后放置四个额外的零字节在passwd上将其中一个识别为NUL终止符。

问题的解决方法是跳过无用的复制:

char *passwd = argv[1];

或者完全删除passwd变量并进行以下比较:

strcmp("LinuxGeek", argv[1])

答案 1 :(得分:2)

当我打印flagpasswd的地址时,我分别得到了0x7fff3315c91c0x7fff3315c910。 所以我得出结论,如果argv [1]的大小大于12(passwdflag的地址之间的差异,passwd的值将覆盖flag的值。 12)。

passwd地址模型(0x7fff3315c910): | 10 | 11 | 12 | ........... | 1A | 1B |

flag地址模型(0x7fff3315c91c): | 1C | ........

从上面我们可以看到flag的地址被passwd

的值覆盖了

答案 2 :(得分:1)

您不对要操作的字符串执行任何检查(长度,空字节),尤其是argv。例如,输入密码可能不适合您的passwd变量。