'C|C語言為了效率或便利而不考慮安全的一些語法特性'

C語言 編譯器 程序員 小智雅匯 2019-08-28
"

C語言是效率最高的高級語言,也是最不安全的高級語言。

作為強類型語言,且類型檢查是其安全和效率所在,但與此同時,類型的隱式轉換(表達式計算、賦值、函數的實參與形參的結合與返回以及邏輯類型),簡單粗暴的顯式類型轉換也會造成安全隱患。

C語言的設計就效率與安全的考量而言,是將效率放在首位的,而假定程序員能避開所有安全的陷阱。

1 指針變量的語法設計和動態內存的直接使用

指針能直接操作內存,是其便捷所在,但也是一把雙刃劍,缺乏內存檢查機制,其所帶來的安全隱患也是很大的;

常見的指針問題有訪問空指針、使用野指針、返回指向臨時變量的指針,試圖修改指針指向的常量等。

動態內存分配是否成功並不做自動檢查。不像C++的new,C的malloc()沒有內置了sizeof、類型轉換和類型安全檢查功能。

2 變量的初始化

C編譯器只初始化全局或靜態變量(包括此種類型的指針變量),其它變量(包括指針變量)都不做初始化,未初始化的變量其值總是隨機的,有很大的安全隱患,特別是將未初始化的值用做下標或與指針一起運算時。

3 變量的值溢出並不做邊界檢查

數據類型都是有值域或邊界的,C編譯器並做這種邊界檢查(上溢或下溢),如:

\tunsigned int i = 0;
\tcout<<~i+1;
\tchar c='f';
\tcout<<(char)(c+555);
\tint fac =1;
\tfor(int i=1;i<18;i++)
\t\tfac*=i;

4 數組邊界與緩衝區溢出

數組、C風格字符串及其標準庫的相關字符串函數、甚至vector類都不做邊界檢查。內在越界訪問有讀越界與寫越界(也就是緩衝區溢出)。字符串緩衝區溢出不單只是程序本身運行的安全問題,還很容易被利用,覆蓋棧幀上寄存器EIP的值,而跳轉到shellcode(一段16進制編碼的語句塊,偽裝成了字符串)。

#include <iostream>
using namespace std;
void main()
{
\tint i =555;
\tint arr[]={1,2,3,4};
\tcout<<arr[4]<<endl;
\tchar str[4];
\tstrcpy(str,"abcde");
\tcout<<str<<endl;
\tgets(str);
\tcout<<str<<endl;
system("pause");
}
輸出:
555
abcde
1234567
1234567

5 邏輯運算符的短路運算

int a=2,b=4,i=0,x;
x=a>b&&++i;

6 邏輯型的語法定義

C語言將非0值做為真值,0值做為假值,帶來使得的同時,也會帶來一些問題。

7 廣義上的整型包括字符、邏輯型;

8 free的簡單性處理

free只是簡單切斷了指針與內在塊的聯繫,指針並沒有置NULL,內在塊的地址屬性也並沒有改變,只是將這塊內置重新鏈接到了堆的可用鏈接表中。

9 預處理無法做類型檢查

其用#define定義的常量並沒有類型檢查,其#define定義的含參數的含義的安全性也沒有C++的inline好。

10 函數參數與返回值的有效性並沒有什麼檢查

在函數體的“入口處”,並沒有對參數的有效性進行檢查,return 語句是否返回指向“棧內存”的“指針”或者“引用”也並沒有檢查。

11 文件指針也並不做NULL檢查

C編譯器做open()函數是否返回NULL也並不做檢查。

-End-

"

相關推薦

推薦中...