當(dāng)前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀] 1. gets()函數(shù)Q:下面的代碼中隱含著安全問題,能發(fā)現(xiàn)嗎? 1 #include 2 int main(void) 3 { 4   char buff[10]; 5   mems

1. gets()函數(shù)
Q:下面的代碼中隱含著安全問題,能發(fā)現(xiàn)嗎?

 1 #include
 2 int main(void)
 3 {
 4   char buff[10];
 5   memset(buff,0,sizeof(buff));
 6 
 7   gets(buff);
 8 
 9   printf("n The buffer entered is [%s]n",buff);
10 
11   return 0;
12 }

?

A:問題在于gets()函數(shù),這個函數(shù)是接收標(biāo)準(zhǔn)輸入的一串字符串,并且沒有檢查字符串緩沖區(qū)的大小就
直接拷貝到buff數(shù)組中,這可能導(dǎo)致在寫入buff內(nèi)存時溢出,可以使用fgets()函數(shù)代替這個函數(shù),

char?*fgets( char?*str,int?n,FILE?*stream );

?

2.strcpy()函數(shù)
Q:下面代碼是一個密碼驗證的過程,是否可以在不知道密碼的情況下驗證通過

 1 #include
 2 #include 
 3 
 4 int main(int argc, char *argv[])
 5 {
 6 
 7   char passwd[10];
 8   int flag = 0;
 9   memset(passwd,0,sizeof(passwd));
10 
11   strcpy(passwd, argv[1]);
12 
13   if(0 == strcmp("LinuxGeek", passwd))
14   {
15     flag = 1;
16   }
17 
18   if(flag)
19   {
20     printf("n Password cracked n");
21   }
22   else
23   {
24     printf("n Incorrect passwd n");
25 
26   }
27   return 0;
28  }

?

A:strcpy()函數(shù)沒有驗證輸入的字符串長度,所有在執(zhí)行時可能出現(xiàn)寫內(nèi)存出現(xiàn)溢出,這很危險,如這代碼,
flag是初始化為0的,當(dāng)內(nèi)存溢出時可能會寫到flag內(nèi)存中,這會使得flag內(nèi)存不為0,即使不執(zhí)行if語句的
比較flag也為真,所以就相當(dāng)于密碼正確

如: $ ./psswd aaaaaaaaaaaaa 輸出: Password cracked

可以使用strncpy()函數(shù)代替
現(xiàn)在編譯器也發(fā)現(xiàn)這種情況,所以在為程序分配內(nèi)存時是分散的分配內(nèi)存,如果要看到上面執(zhí)行的情況,使用gcc的話
可以使用 ‘-fno-stack-protector’參數(shù)(我沒驗證)

3.main()函數(shù)的返回類型
Q:下面代碼是否能編譯通過?是否還存在其他問題

 1 #include
 2 
 3 void main(void)
 4 {
 5   char *ptr = (char*)malloc(10);
 6 
 7   if(NULL == ptr)
 8   {
 9     printf("n Malloc failed n");
10     return;
11   }
12   else
13   {
14     // Do some processing
15 
16     free(ptr);
17   }
18 
19   return;
20 }

A:對于現(xiàn)在的編譯器這段代碼是可以編譯通過的,不過是會有警告,main()返回類型最好使用int類型,
當(dāng)一個函數(shù)執(zhí)行結(jié)束時最后返回一個狀態(tài)值,現(xiàn)在C/C++返回一個0值表示程序正常退出,否則有異常.

4.內(nèi)存泄露
Q:下面代碼執(zhí)行結(jié)果會出現(xiàn)內(nèi)存泄露嗎?

 1 #include
 2 
 3 void main(void)
 4 {
 5   char *ptr = (char*)malloc(10);
 6 
 7   if(NULL == ptr)
 8   {
 9     printf("n Malloc failed n");
10     return;
11   }
12   else
13   {
14     // Do some processing
15   }
16 
17   return;
18 }

A:其實內(nèi)存泄露是個很嚴(yán)重的問題,其實上面代碼執(zhí)行結(jié)果不會出現(xiàn)內(nèi)存泄露,雖然沒有使用free()
回收內(nèi)存,但是當(dāng)程序執(zhí)行結(jié)束后程序里分配的內(nèi)存會自動釋放,如果是分配的內(nèi)存放到一個死循環(huán)里
就會出現(xiàn)嚴(yán)重的內(nèi)存泄露,或者程序一直執(zhí)行著,動態(tài)分配的內(nèi)存會一直占有著無法釋放.
有篇文章介紹了內(nèi)存泄露的檢測方法:http://www.cnblogs.com/skynet/archive/2011/02/20/1959162.html

5.free()函數(shù)
Q:下面代碼執(zhí)行時輸入如 ‘freeze’會崩潰但輸入如t ‘zebra’就不會為什么?

 1 #include
 2 
 3 int main(int argc, char *argv[])
 4 {
 5     char *ptr = (char*)malloc(10);
 6 
 7     if(NULL == ptr)
 8     {
 9         printf("n Malloc failed n");
10         return -1;
11     }
12     else if(argc == 1)
13     {
14         printf("n Usage  n");
15     }
16     else
17     {
18         memset(ptr, 0, 10);
19 
20         strncpy(ptr, argv[1], 9);
21 
22         while(*ptr != 'z')
23         {
24             if(*ptr == '')
25                 break;
26             else
27                 ptr++;
28         }
29 
30         if(*ptr == 'z')
31         {
32             printf("n String contains 'z'n");
33             // Do some more processing
34         }
35 
36        free(ptr);
37     }
38 
39     return 0;
40 }

A:這個問題主要是指針移到的問題,當(dāng)輸入如‘zebra’這樣的字符串('z'開頭)時,ptr指針沒有移到,所以
ptr指針指向的內(nèi)存還是malloc分配的原內(nèi)存的起始地址,但是輸入‘freeze’時,ptr指針移到了,已經(jīng)不是指向原來
分配的內(nèi)存的起始地址了,所有free時就會出錯

題外話:在實現(xiàn)如strcpy的函數(shù)時,如下

 1 char *strcpy(char *strDest, const char *strSrc)
 2 {
 3     assert((strDest != NULL) && (strSrc != NULL));
 4     
 5     if(strDest == strSrc)
 6     return strDest; //注意這個.. 
 7 
 8     char *pstr = strDest; //保存原始地址
 9     while((*strDest++ = *strSrc++) != '