一道C語言安全編碼題目

2022-03-08 13:37:09 字數 3351 閱讀 9014

1、前言

最近在網上看到一道c語言題目,用c語言實現乙個函式,給定乙個int型別的整數,函式輸出逆序的整數,例如輸入123,則輸出字串"321",,輸入-123,則輸出字串"-321"。題目要求,不使用標準庫,不得分配記憶體。當時覺得蠻簡單的,這不就是類似字串逆轉嘛,自己嘗試做了一下,測試發現,還是有很多地方考慮不周全。今天在此整理一下基礎知識,作為一名安全開發人員,時刻需要注意**的安全,防止有任何漏洞。題目給出的函式如下:

#include const

char * parseint(int

data)

intmain()

2、思考過程寫**最怕的就是沒有想好,一上來就寫,在寫的過程中不斷的測試修改,這樣很浪費時間。因此需要先好好想一下,這個題目到底考些什麼呢?

(1)int型別的整數分為正數、0、負數,如何處理這些邊界值

(2)整數與字串之間的轉換,如何將乙個整數轉換為乙個字元

(3)如何返回乙個const char * 型別的字串

(4)當輸入的整數超過int的範圍如何處理

3、編碼過程

開始寫**的思路如下:定義乙個char型別的陣列,用於儲存結果。使用對10取餘和除法操作依次獲取每一位的數字,然後根據assic碼轉換為字元。將字元拼接起來,返回字串陣列結果。編碼實現如下:

const

char * parseint(int

data)

;

int i = 0

;

if (data < 0

)

int tmp =data;

while (tmp / 10

) str[i++] = tmp % 10 + 48

;return

str;

}

當初沒有考慮那麼多,編譯發現出現如下錯誤:

一看編譯錯誤,才意識到自己掉入坑中。題目要求返回乙個字串,而且不用分配記憶體。當時就想直接定義乙個字元陣列進行返回,而定義的str屬於函式區域性變數。

乙個函式的區域性變數都是存在stack中的,當這個函式呼叫過程結束時,這個區域性變數都是要釋放掉的,所以就會產生這樣的warning,這個是和變數的life time相關的,所以解決方法有:

1.將char result[16]改為static型

2.使用malloc向heap申請,這些是需要caller用free去釋放的

於是使用static 型別字串,**改進如下:

1

const

char * parseint(int

data)2;

4int i = 0;5

6if (data < 0

)

1011

int tmp =data;

12while (tmp / 10 != 0

)

18 str[i++] = tmp % 10 + 48

; 20

return

str;

21 }

int main()

測試結果如下:

改為static之後,編譯成功,看輸出的結果上看,前面兩個輸出是正確的,而第三個輸出的結果是錯誤的。尼瑪,再次掉入坑中,對static變數的應用不精通啊。為什麼每次到看到結果後才想起來?

雖然在函式中定義了static區域性變數,使得變數的變為靜態stack儲存區域,生命週期從函式中變成了這個程式的範圍。但是static區域性變數在函式第一次呼叫的時候會初始化,後面呼叫就不會了,直接使用了。因此導致了剛才的結果輸出不對,復用了上次遺留的結果。

static靜態區域性變數屬於靜態儲存方式,它具有以下特點:

(1)靜態區域性變數在函式內定義 它的生存期為整個源程式,但是其作用域仍與自動變數相同,只能在定義該變數的函式內使用該變數。退出該函式後, 儘管該變數還繼續存在,但不能使用它。

(2)允許對構造類靜態區域性量賦初值 例如陣列,若未賦以初值,則由系統自動賦以0值。

(3)對基本型別的靜態區域性變數若在說明時未賦以初值,則系統自動賦予0值。而對自動變數不賦初值,則其值是不定的。 根據靜態區域性變數的特點, 可以 看出它是一種生存期為整個源程式的量。雖然離開定義它的函式後不能使用,但如再次呼叫定義它的函式時,它又可繼續使用, 而且儲存了前次被呼叫後留下的 值。 因此,當多次呼叫乙個函式且要求在呼叫之間保留某些變數的值時,可考慮採用靜態區域性變數。雖然用全域性變數也可以達到上述目的,但全域性變數有時會造成 意外的***,因此仍以採用區域性靜態變數為宜。

第一次呼叫函式,static變數,初始化。

第二次,及以後,呼叫函式,static變數,不會初始化。

繼續改進**,在函式中將static變數每次使用for迴圈進行初始化,改進**如下:

1 #include 2

3const

char * parseint(int

data)4;

6int i = 0;7

8 int t = 0;

9 for (; t < 16; t++)

12 13

if (data < 0

) 17

18int tmp =data;

19while (tmp / 10 != 0

) 24

25 str[i++] = tmp % 10 + 48;26

27return

str;28}

2930

intmain()

31

這次輸出結果如下:

這個結果是什麼呢?為什麼會這樣呢?

printf("

%s\n

", parseint(0x8fffffff));

printf("%s\n", parseint(0xffffffff));

這個結果是什麼呢?為什麼會這樣呢?

int 型別4個位元組,32位組成。int的最高位作為符號位,需要特殊處理。

實際執行結果如下:

一道C語言安全編碼題目

1 前言 最近在網上看到一道c語言題目,用c語言實現乙個函式,給定乙個int型別的整數,函式輸出逆序的整數,例如輸入123,則輸出字串 321 輸入 123,則輸出字串 321 題目要求,不使用標準庫,不得分配記憶體。當時覺得蠻簡單的,這不就是類似字串逆轉嘛,自己嘗試做了一下,測試發現,還是有很多地...

記錄一道C語言題目

很簡單的乙個題。磨磨腦子,最近有點手生。題目 統計各位數字之和是5的數 本題要求實現兩個函式 乙個函式判斷給定正整數的各位數字之和是否等於5 另乙個函式統計給定區間內有多少個滿足上述要求的整數,並計算這些整數的和。我講得可能不算很清楚,具體請檢視題目鏈結 實現 include include def...

每天一道C語言題目

從今天開始我每天最少會做一道c語言的題目。題目 include int main 我們知道型別的自動轉換,也就是char進行運算的時候,會自動轉換為int。b 輸出b,b是字元,理所當然輸出 2 然後b 相等於b b 1 b 1的結果是int型別的51,而不是字元 3 只是把這個int型別的51賦給...