2012-04-23 41 views
-3

我在写C一个简单的程序奇怪的括号:小C程序

int main(int argc, char** argv) { 
    unsigned char* line = (unsigned char*) malloc(0xFFFF); 
    while (gets(line) > 0) { 
     if (line[0] == 'l') { 
      if (line[2]=='.' && line[3] == '.') { 
       printf("forbidden path"); 
      } 
      unsigned char* res = (unsigned char*) malloc(0xFFFF); 
      unsigned char* cmd = (unsigned char*) malloc(strlen(line) + 
      1 + strlen(" | grep -v xml") + strlen("/home/files/")); 
      strcpy(cmd, "ls "); 
      strcpy(cmd + 3, "/home/boris/0servfiles/"); 
      strcpy(cmd + 3 + strlen("/home/files/"), line + 2); 
      strcpy(cmd + 3 + strlen("/home/files/") + strlen(line + 2), " | grep -v xml"); 
      execwthr(cmd, res); 
      printf("%s\n%s", cmd, res); 
      free(cmd); 
      free(res); 
     } else if (line[0] == 'm') { 
      if (line[2]=='.' && line[3] == '.') { 
       printf("forbidden path"); 
      } 
      unsigned char res = (unsigned char*) malloc(0xFFFF); 
      unsigned char* cmd = (unsigned char*) malloc(strlen(line) + 
       1 + strlen("/home/files/")); 
      strcpy(cmd, "mkdir "); 
      strcpy(cmd + 6, "/home/files/"); 
      strcpy(cmd + 6 + strlen("/home/files/"), line + 2); 
      execwthr(cmd, res); 
      printf("%s\n%s", cmd, res); 
      free(cmd); 
      free(res); 
     } 
    } 
    return (EXIT_SUCCESS); 
} 

还有一个小问题。当我尝试创建一个名为“h”的文件夹时,我得到以下结果:

m l 
mkdir /home/files)l 

怎么了?提前致谢!

+6

甜蜜的耶稣,这是什么代码? – Tibor 2012-04-23 21:22:18

+0

这段代码太难看了,它会伤害我的眼睛 – JosephH 2012-04-23 21:25:05

+2

**调试提示:**分别解决字符串操作和与文件系统交互的问题。事实上,这些是将这个问题分解为功能的两名体面候选人。 – dmckee 2012-04-23 21:25:49

回答

2

这里有很多问题。我会列举一些,解决它们可能会使其他人更加明显。

当出现意外路径作为输入时,可以打印出“禁止路径”。但是,使用该无效路径继续执行该功能。发生这种情况时,您可能希望完全排除程序。

malloc()函数可能会失败。当它发生时,它返回一个NULL指针。您从不检查由malloc返回的值,这意味着您的字符串操作代码可能正在使用无效指针。

您不应该使用像strcpy()这样的函数,因为它们不会防止缓冲区溢出。改用“安全”版本(如strncpy)。

函数gets()是痛苦的不安全的并且已被弃用。改用其他标准库I/O函数。

此代码:

strcpy(cmd, "ls "); 
strcpy(cmd + 3, "/home/boris/0servfiles/"); 
strcpy(cmd + 3 + strlen("/home/files/"), line + 2); 

很可能无法做你想要做的事。第二行向缓冲区添加一个长字符串,但第三行只向前跳过足够多,以容纳更短的字符串。这意味着你的第三个strcpy这里会部分覆盖第二个strcpy所写的字符串。

这样的代码:

strcpy(cmd, "mkdir "); 
strcpy(cmd + 6, "/home/files/"); 
strcpy(cmd + 6 + strlen("/home/files/"), line + 2); 

是容易出错的,充满魔力的数字。如果我正在解释你正在做的事情,你可以把它合并成一个更有意义的呼叫:sprintf(cmd, "mkdir /home/files/%s", line + 2);

正如其他人所提到的,您似乎正在重新执行标准strncat()函数。你应该明智地使用标准版本。如果你正在处理这样的硬编码字符串,我甚至建议使用snprintf()

下面一行是错误的:

unsigned char res = (unsigned char*) malloc(0xFFFF); 

你分配一个指向char,这几乎可以肯定是不是你想要的。

您动态分配内存line,但你永远不会释放它。

+1

'malloc'失败是他最担心的问题。并且['strncpy'不一定是null-terminate它的输出](http://stackoverflow.com/questions/1453876/why-does-strncpy-not-null-terminate)。 – 2012-04-23 21:54:03

2

您似乎没有意识到strcat()函数。使用它将大大简化您的代码。

此外,为什么您要编写C代码来完成一项可以通过简单的shell(或Perl)脚本轻松完成的工作?举例来说,我相信你的脚本将看起来像这样在Perl:

#!/usr/bin/perl 
use strict; 
while (my $line = <STDIN>) { 
    chomp $line; 
    my $cmd; 
    if (my ($arg) = $line =~ m{^l (.*)$}) { 
     $cmd = "ls /home/files/$arg | grep -v xml"; 
    } elsif (my ($arg) = $line =~ m{^m (.*)$}) { 
     $cmd = "mkdir /home/files/$arg"; 
    } 
    my $res = `$cmd`; 
    print "$cmd\n$res\n"; 
} 

请注意,此代码是未经测试,它的(仍然)是不安全的。然而,它比你的代码更短,更容易阅读。这表明C是这项任务的错误语言。 :)

1

此代码是非常糟糕的。请参考strcat()函数。

我也看到很多其他问题。例如,如果代码确定输入了“禁止路径”,则该代码将继续执行该任务!

您将从学习如何使用调试器来浏览此代码并查看它实际执行的操作中受益。这也可以让你能够回答你原来的问题。

0

基本上所有的丑陋代码都可以用正确的参数调用snprintf来代替。不要打扰学习strcat;而正如其他人所说的那样,它会比你所做的更容易,而且它还可以很容易地编写易受攻击的代码。只需使用snprintf即可满足您所有的字符串生成需求,并且您的代码将变得干净,简单,甚至具有无错的机会。