2012-04-23 46 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即可滿足您所有的字符串生成需求,並且您的代碼將變得乾淨,簡單,甚至具有無錯的機會。