-2

我正在用 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

怎么了?提前致谢!

4

4 回答 4

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 语言不适合这项任务。:)

于 2012-04-23T21:24:07.380 回答
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);

您正在分配一个指向 a 的指针char,这几乎肯定不是您想要的。

您为 动态分配内存line,但从不释放它。

于 2012-04-23T21:50:35.380 回答
1

这段代码很糟糕。请参考strcat()函数。

我还看到了许多其他问题。例如,如果代码确定输入了“禁止路径”,那么它将继续执行任务!

您将受益于学习如何使用调试器来单步执行此代码并查看它的实际作用。这也将使您也能够回答您的原始问题。

于 2012-04-23T21:24:39.267 回答
0

Basically all of your ugly code could be replaced by a single call to snprintf with the right arguments. Don't bother learning strcat; while, as others have said, it will be easier than what you're doing, it also makes it easy to write vulnerable code. Just use snprintf for all your string-producing needs and your code will be clean, simple, and even has a decent chance of being bug-free.

于 2012-04-23T23:33:06.593 回答