1. gets()函數(shù)
Q:下面的代碼中隱含著安全問(wèn)題,能發(fā)現(xiàn)嗎?
1 #include2 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:問(wèn)題在于gets()函數(shù),這個(gè)函數(shù)是接收標(biāo)準(zhǔn)輸入的一串字符串,并且沒(méi)有檢查字符串緩沖區(qū)的大小就
直接拷貝到buff數(shù)組中,這可能導(dǎo)致在寫(xiě)入buff內(nèi)存時(shí)溢出,可以使用fgets()函數(shù)代替這個(gè)函數(shù),
char
?*
fgets
(
char
?*str,
int
?n,
FILE
?*stream
);
?
2.strcpy()函數(shù)
Q:下面代碼是一個(gè)密碼驗(yàn)證的過(guò)程,是否可以在不知道密碼的情況下驗(yàn)證通過(guò)
1 #include2 #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ù)沒(méi)有驗(yàn)證輸入的字符串長(zhǎng)度,所有在執(zhí)行時(shí)可能出現(xiàn)寫(xiě)內(nèi)存出現(xiàn)溢出,這很危險(xiǎn),如這代碼,
flag是初始化為0的,當(dāng)內(nèi)存溢出時(shí)可能會(huì)寫(xiě)到flag內(nèi)存中,這會(huì)使得flag內(nèi)存不為0,即使不執(zhí)行if語(yǔ)句的
比較flag也為真,所以就相當(dāng)于密碼正確
如:
$ ./psswd aaaaaaaaaaaaa
輸出:
Password cracked
可以使用strncpy()函數(shù)代替
現(xiàn)在編譯器也發(fā)現(xiàn)這種情況,所以在為程序分配內(nèi)存時(shí)是分散的分配內(nèi)存,如果要看到上面執(zhí)行的情況,使用gcc的話
可以使用 ‘-fno-stack-protector’參數(shù)(我沒(méi)驗(yàn)證)
3.main()函數(shù)的返回類型
Q:下面代碼是否能編譯通過(guò)?是否還存在其他問(wèn)題
1 #include2 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:對(duì)于現(xiàn)在的編譯器這段代碼是可以編譯通過(guò)的,不過(guò)是會(huì)有警告,main()返回類型最好使用int類型,
當(dāng)一個(gè)函數(shù)執(zhí)行結(jié)束時(shí)最后返回一個(gè)狀態(tài)值,現(xiàn)在C/C++返回一個(gè)0值表示程序正常退出,否則有異常.
4.內(nèi)存泄露
Q:下面代碼執(zhí)行結(jié)果會(huì)出現(xiàn)內(nèi)存泄露嗎?
1 #include2 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:其實(shí)內(nèi)存泄露是個(gè)很嚴(yán)重的問(wèn)題,其實(shí)上面代碼執(zhí)行結(jié)果不會(huì)出現(xiàn)內(nèi)存泄露,雖然沒(méi)有使用free()
回收內(nèi)存,但是當(dāng)程序執(zhí)行結(jié)束后程序里分配的內(nèi)存會(huì)自動(dòng)釋放,如果是分配的內(nèi)存放到一個(gè)死循環(huán)里
就會(huì)出現(xiàn)嚴(yán)重的內(nèi)存泄露,或者程序一直執(zhí)行著,動(dòng)態(tài)分配的內(nèi)存會(huì)一直占有著無(wú)法釋放.
有篇文章介紹了內(nèi)存泄露的檢測(cè)方法:http://www.cnblogs.com/skynet/archive/2011/02/20/1959162.html
5.free()函數(shù)
Q:下面代碼執(zhí)行時(shí)輸入如 ‘freeze’會(huì)崩潰但輸入如t ‘zebra’就不會(huì)為什么?
1 #include2 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:這個(gè)問(wèn)題主要是指針移到的問(wèn)題,當(dāng)輸入如‘zebra’這樣的字符串('z'開(kāi)頭)時(shí),ptr指針沒(méi)有移到,所以
ptr指針指向的內(nèi)存還是malloc分配的原內(nèi)存的起始地址,但是輸入‘freeze’時(shí),ptr指針移到了,已經(jīng)不是指向原來(lái)
分配的內(nèi)存的起始地址了,所有free時(shí)就會(huì)出錯(cuò)
題外話:在實(shí)現(xiàn)如strcpy的函數(shù)時(shí),如下
1 char *strcpy(char *strDest, const char *strSrc) 2 { 3 assert((strDest != NULL) && (strSrc != NULL)); 4 5 if(strDest == strSrc) 6 return strDest; //注意這個(gè).. 7 8 char *pstr = strDest; //保存原始地址 9 while((*strDest++ = *strSrc++) != '