遊戲開發中的靜態分析:?十大軟體漏洞
作者: Sergey Vasiliev
本文節選翻譯自Sergey Vasiliev的文章。
遊戲開發中的靜態分析:
十大軟體漏洞
為什麼要使用靜態分析
主要原因如下:
隨著時間的推移,修復錯誤的成本和難度不斷上升。靜態分析的主要優點之一是,能在早期開發階段檢測錯誤(在編寫代碼時可以發現錯誤)。因此,通過使用靜態分析,方便程序員在開發階段發現問題,並在釀成大錯之前對其進行改正。
靜態分析工具可以識別各種錯誤(複製粘貼,拼寫錯誤,錯誤使用函數等)。
靜態分析通常能檢測到動態分析檢測不出的錯誤,反之亦然。
靜態分析也可能出現誤報的狀況。解決方法方法包括各種警告抑制機制,關閉不相關的診斷,以及排查出錯的文件和文件夾。通過適當調整分析儀的設置,可以減少誤報。
01
使用靜態分析的例子
虛幻引擎中的靜態分析
PVS-Studio團隊與Epic Games合作了幾次,以協助Epic Games在(虛幻引擎)項目中使用靜態分析發現並修復錯誤。這種合作為虛幻引擎添加了一個特殊的標誌,開發人員能將靜態分析集成到虛幻引擎項目的構建系統中。
GIF
John Carmack進行靜態分析
John Carmack是最著名的遊戲開發商之一,他曾經說過,靜態分析的採用是他作為程序員最重要的成就之一。
「近年來我作為程序員所做的最重要的事情就是積極地追求靜態代碼分析。」 下次聽到有人說靜態分析是新手的工具時,記得讓他們來看看Carmack的文章。
02
使用靜態分析發現的十大遊戲軟體漏洞
第十名
第十位是《迷失地帶》遊戲中使用的X-Ray引擎中的錯誤。玩過《迷失地帶》的人,肯定記得遊戲里有很多有趣的錯誤,下面就是其中之一。
PVS-Studio警告:V530 需要使用「空」功能的返回值。
程序員沒有使用空方法返回的邏輯值來描述容器是否為空。
GIF
第九名
第九名依舊是遊戲引擎中的錯誤。這次是來自Cry引擎 V的代碼片段。使用了這個引擎的遊戲中出現的錯誤的數量不算特別多,但也有很多可疑的碎片。
PVS-Studio警告:V519 "BlendFactor [2]"變數連續兩次賦值。也許這是一個錯誤。
正如文章中多次提到的那樣,沒有人能免於拼寫錯誤。實事實證明靜態分析非常擅長檢測拼寫錯誤。在上面的代碼中,m_auBlendFactor數組的值被複制到BlendFactor數組,但程序員通過編寫BlendFactor [2]兩次犯了錯誤。結果,m_auBlendFactor [3]的值寫入BlendFactor [2],而BlendFactor [3]的值保持不變。
GIF
第八名
看一下C#代碼。這個例子來自《太空工程師》,這是一個在太空中建造和維護各種建築設備的「沙盒」遊戲。
PVS-Studio警告:
V3010 需要使用函數"Format"的返回值。
V3010 需要使用函數"Format"的返回值。
這是C ++代碼和C#代碼的常見問題,程序員忽略方法的返回值。String.Format方法根據格式字元串和要替換的對象形成結果字元串,然後返回。在上面的代碼中,else-branch包含兩個string.Format調用,但沒有它們的返回值。
看起來程序員打算通過MySandboxGame.Log.WriteLine的方法,使用與if語句的then-branch中相同的方式來記錄這些消息。
GIF
第七名
靜態分析能很好地檢測錯別字的另一個例子。
PVS-Studio警告:V537 查看「scale_x」項目用法的正確性。
變數x和y是賦值,但兩個表達式都包含p-> scale_x子表達式。第二個子表達式應該是p-> scale_y。
GIF
第六名
Unity Technologies最近公開了其專有遊戲引擎Unity的代碼,使用靜態分析,發現了許多有趣的代碼片段:
PVS-Studio警告:V3063 如果計算條件的一部分表達如此,則結果始終為:pageSize
這裡有一個不正確的pageSize範圍檢查。程序員打算檢查pageSize值是否在[1; 1000],但卻犯了一個可怕的錯誤,運算符輸入成了"||",而不是"&&"。子表達式實際上沒有檢查任何內容。
GIF
第五名
在Unity3D的組件中發現的一個很好的錯誤。
PVS-Studio警告:V3080 可能有空的引用。考慮檢查"t.staticFieldBytes"。
請注意將lambda表達式作為參數傳遞給Where方法。該代碼表明typeDescriptions集合可以包含其staticFieldBytes成員可以為null的元素,因此在訪問Length屬性之前檢查staticFieldBytes!= null。然而,程序員混淆了"&"和"&&"運算符。這意味著無論左表達式的結果(true / false),還將評估正確的結果,如果staticFieldBytes == null,則在訪問Length屬性時會引發NullReferenceException。使用"&&"運算符可以幫助避免這種情況,因為如果staticFieldBytes == null,則不會計算正確的表達式。
雖然Unity是唯一一個兩次進入這個名單的引擎,但這並不影響遊戲製作人們用它來製作出精彩的遊戲。
GIF
第四名
Godot 引擎中有一個關於缺失的關鍵字的例子。
GIF
第三名
第三名是《毀滅戰士3》中源代碼的一小段。
PVS-Studio警告:V575 "memset"函數處理"0"元素。檢查第三個參數。
要想解決這個錯誤,我們應該回想一下memset函數的簽名:
如果將它與上面的調用進行比較,你會注意到最後兩個參數的位置對調了,這就導致了一些要被清除的內存塊將保持不變。
GIF
第二名
第二名是用C#編寫的Xenko遊戲引擎代碼中的錯誤。
PVS-Studio警告:V3065 參數"height"未在方法體內使用。
程序員在將參數傳遞給CreateDescription時犯了一個錯誤。觀察它的簽名,可以看到第二,第三和第四個參數分別命名為width,height和depth。但是調用傳遞了參數width,width和depth。
GIF
第一名
第一名的錯誤來自虛幻引擎4。
PVS-Studio警告:V564 "&"運算符應用於bool類型值。你可能忘記包含括弧或打算使用"&&"運算符。
你肯定會想知道,這段代碼中哪裡用"&"代替了"&&"。如果我們簡化if語句的條件表達式,請記住VertInfluencedByActiveBone函數的最後一個參數有一個默認值,這將清除它:
仔細看看最後一個子表達式:
這個帶有默認值的參數把事情搞砸了:對於這個值,它的代碼根本就沒有被編譯過。但是因為它存在,代碼編譯成功並且與bug融合在一起。這是分析器發現的可疑片段——左操作數為bool,右操作數為int32。
03
結論
靜態分析對於遊戲和遊戲引擎開發來說是一個非常有用的工具,它可以幫助你提高代碼質量,從而提高最終產品的質量。
以上就是本期乾貨分享的全部內容啦~
想獲取更多資訊,記得關注我們喲~
※開發人員如何實現4K遊戲
※深度探究《極限競速地平線3》中的無障礙合作
TAG:西山居技術 |