12個滑稽的C語言面試問答——《12個有趣的C語言問答》評析(1)

  不止一次在網上看到一篇名爲《12個有趣的C語言問答》的博文被鄭重其事地轉來轉去( google了一下,竟然有154,000條結果,其中不乏一些知名的技術網站),感到很是滑稽。由於那明擺着是一篇垃圾文,質量低下,漏洞比比皆是。其中基本上沒有多少技術養分,卻是有不少技術毒素。html

  這篇垃圾文被轉反覆載的緣由可能有兩個:一是標題取的好,其中有「有趣」二字,很多很傻很天真的人就覺得真的頗有趣;第二個緣由多是這是一篇翻譯文章,原文爲12 Interesting C Interview Questions and Answers,有些人潛意識裏可能覺得外文的東西會頗有技術含量。但實際上洋文中也有垃圾,洋人中也有不少外行,正如國外也有老譚《C語言程序設計》那種門外漢寫得暢銷垃圾書(譬如郵電社翻譯的《寫給你們看的C語言書》,參見劣質代碼評析——《寫給你們看的C語言書(第2版)》附錄B之21點程序(一) )同樣。對國外的東西一樣不能盲從輕信,不能根據暢銷程度或轉發多少更不能僅僅根據其名字來判斷技術價值。數組

  下面對這篇《12個有趣的C語言問答》垃圾文,參照其出處(由於翻譯本有不少錯誤),簡要地評析一下。但願對垃圾文的不斷擴散多少能起到點遏制的做用。 promise

 

0. gets() 方法
Q:如下代碼有個被隱藏住的問題,你能找到它嗎? dom

int main(void) 
{ 
    char buff[10]; 
    memset(buff,0,sizeof(buff)); 
  
    gets(buff); 
  
    printf("\n The buffer entered is [%s]\n",buff); 
  
    return 0; 
}

 A:這個不顯眼的問題就是使用了 gets() 方法。此方法接受一個string類型參數,可是卻沒有檢測此數值是否 有足夠的空間來拷貝數據。因此這裏咱們通常用 fgets() 方法未來的更好。函數


Answer: The hidden problem with the code above is the use of the function gets(). This function accepts a string from stdin without checking the capacity of buffer in which it copies the value. This may well result in buffer overflow. The standard function fgets() is advisable to use in these cases.oop

 

評:  

  翻譯很成問題。根據原文,是「gets()函數」,不是「gets()方法」;接受一個string參數,不是「string類型參數」(C語言中根本沒有這種類型)。其他部分的翻譯也有問題,但對原意影響不大,就很少說了。  post

  Answer中說使用gets()函數可能致使buffer的overflow,這一點沒什麼疑問。由於這個緣故,C語言如今已經廢棄了gets()函數。
  問題在於代碼中的網站

    memset(buff,0,sizeof(buff));

這句,這句很無聊得很愚蠢。它的效果是在buff中填充0,但其實根本用不着這樣調用函數來實現,只須要簡單地this

    char buff[10] = { '\0' };

就足夠了。更重要的是,從後面對buff的使用來看,根本不必在buff中填充0。 google

 

1,strcpy() 方法 
Q:
密碼防禦是很基本的功能,看看可否搞定下面這段代碼

#include<stdio.h>

int main(int argc, char *argv[])
{
    int flag = 0;
    char passwd[10];

    memset(passwd,0,sizeof(passwd));

    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;
}

 

評:

  暈!Answer壓根沒翻譯。那麼多轉來轉去的人竟然對此視而不見! 從這裏就不難看出哪些轉這篇垃圾的人究竟有沒有認真看,究竟有沒有本身的頭腦。這也一樣可以解釋,爲何垃圾能傳播很廣,以及爲何那些說譚浩強的書發行量大就必定好的見解是無腦人的看法。

  根據原文,解答是這樣的: 

Answer: Yes. The authentication logic in above password protector code can be compromised by exploiting the loophole of strcpy() function. This function copies the password supplied by user to the ‘passwd’ buffer without checking whether the length of password supplied can be accommodated by the ‘passwd’ buffer or not. So if a user supplies a random password of such a length that causes buffer overflow and overwrites the memory location containing the default value ’0′ of the ‘flag’ variable then even if the password matching condition fails, the check of flag being non-zero becomes true and hence the password protection is breached.

For example :

  $ ./psswd aaaaaaaaaaaaa

   Password cracked
So you can see that though the password supplied in the above example is not correct but still it breached the password security through buffer overflow.
To avoid these kind of problems the function strncpy() should be used.

 

Note from author : These days the compilers internally detect the possibility of stack smashing and so they store variables on stack in such a way that stack smashing becomes very difficult. In my case also, the gcc does this by default so I had to use the the compile option ‘-fno-stack-protector’ to reproduce the above scenario.

   不翻譯了。這個解答的意思就是經過輸入較長的argv[1],藉助數組越界來改變flag,實現「break」這個程序的目的(Can you break it without knowing the password)。因此應該使用strncpy()。

  這種「break」多少有點歪門邪道的意味,並且做者也提到了,有些編譯器能夠防止這種狀況,因此這種方法其實意義不大。

  這裏想說的依然是代碼風格的問題——那個flag極其醜陋,不只醜陋,沒有必要存在,還進行了沒必要要的初始化。那個

memset(passwd,0,sizeof(passwd));

一樣多此一舉。

  甚至連passwd這個數組都不必,只要直接比較"LinuxGeek"和argv[1]指向的字符串就能夠了。代碼能夠這樣寫: 

#include<stdio.h>

int main(int argc, char *argv[])
{
    //char passwd[10];

    //strncpy(passwd, argv[1], 10);

    if( strcmp("LinuxGeek", argv[1] ) == 0  ) //if( strcmp("LinuxGeek", passwd) == 0  )
    {
        printf("\n Password cracked \n");
    }
    else
    {
        printf("\n Incorrect passwd \n");

    }
    return 0;
}

 簡潔又天然。

 (未完待續)

續文連接:http://www.cnblogs.com/pmer/p/3322429.html

相關文章
相關標籤/搜索