則機制)
靜態(tài)分析SAST應用安全漏洞掃描代碼質(zhì)量【免費下載鏈接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security項目地址https://gitcode.com/gh_mirrors/co/codeql點擊查看免費下載本文圍繞 CodeQL 倉庫中 C 查詢庫的一次重要變更記錄展開SimpleRangeAnalysis范圍分析庫新增了對無符號數(shù)乘法、常量乘法、引用類型函數(shù)參數(shù)、不等比較收窄范圍以及if (x)布爾判零等語言構(gòu)造的支持并且首次開放了通過SimpleRangeAnalysisExpr抽象類注入自定義范圍規(guī)則的擴展點。讀完本文你將理解這些能力背后的格lattice抽象解釋原理、widening 終止性設計并能參考倉庫中的現(xiàn)成示例為自己的查詢添加范圍分析擴展。1. 變更概覽五項新語法支持與自定義規(guī)則能力該變更記錄2020-09-29-range-analysis-rollup.md面向 lgtm 與 codescanning 兩個平臺其核心內(nèi)容可以概括為兩部分第一部分新支持的語言構(gòu)造。SimpleRangeAnalysis庫在此前不支持五類 C 語言構(gòu)造本次變更全部補齊無符號數(shù)的乘法multiplication of unsigned numbers與常量相乘multiplication by a constant引用類型的函數(shù)參數(shù)reference-typed function parameters用“變量不等于其值域端點”的比較收窄范圍——例如x ! c且c是x的當前下界時可將下界向前推進一格用if (x)或if (!x)這類布爾上下文測試“是否等于零”。變更說明同時指出這些改進主要影響三個查詢cpp/constant-comparison、cpp/comparison-with-wider-type和cpp/integer-multiplication-cast-to-long。第二部分可擴展性。庫從此可以接受用戶自定義規(guī)則官方示例存放在變更記錄所列的cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/目錄下。需要說明的是在當前的倉庫結(jié)構(gòu)中這些示例已經(jīng)遷移到了cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/而抽象接口則位于cpp/ql/lib/experimental/semmle/code/cpp/models/interfaces/。2. 原理基礎在 QL 中實現(xiàn)范圍分析的三個關(guān)鍵設計要理解這次變更的價值先看 SimpleRangeAnalysis.qll 文件頭部注釋對算法本身的描述。范圍分析通常是對“值域格”的抽象解釋——每個表達式的抽象值是一對浮點數(shù)(lowerBound, upperBound)。直接用格求最小不動點會遇到收斂過慢的問題文件注釋中給出的經(jīng)典反例是int count 0; for (; p; p p-next) { count count 1; }count的值域從(0,0)出發(fā)每輪不動點迭代只向上推進一格的邊界(0,1)、(0,2)……直到maxInt格的高度幾乎無界。庫給出的對策有三點全部可以直接在源碼中驗證固定 widening 邊界集。當某個定義“遞歸地依賴自身”通過defDependsOnDef的傳遞閉包檢測見 SimpleRangeAnalysis.qll 中的defDependsOnDefTransitively與isRecursiveDef就把它的邊界舍入到一個固定集合。下界集合是2, 1, 0, -1, -2, -8, -16, -128, -256, -32768, -65536, typeLowerBound, -Inf上界集合是對稱的-2, -1, 0, 1, 2, 7, 15, 127, 255, 32767, 65535, typeUpperBound, InfwideningLowerBounds / wideningUpperBounds。注釋明確說這與抽象解釋中的 widening 技術(shù)類似但因為 QL 無法查看上一輪迭代的邊界精度略低——例如 widening 可能推出下界-11而這里只能近似為-16。用浮點數(shù)表示邊界。注釋解釋了動機浮點不會溢出回繞且可以通過“邊界落在類型可表示范圍之外”直接檢測正/負溢出getTruncatedLowerBounds與getTruncatedUpperBounds分別處理了這種不可表示邊界的截斷見 SimpleRangeAnalysis.qll。先收集邊界集合、后聚合。由于 QL 不允許在遞歸子表達式上做聚合aggregate遞歸階段為每個表達式產(chǎn)生“一組下界”和“一組上界”最小下界與最大上界在遞歸結(jié)束后才計算。這條限制還引出了一個性能護欄BoundsEstimate模塊在分析前估計邊界數(shù)量一旦超過2^29的上限getBoundsLimitSimpleRangeAnalysis.qll就提前啟用 widening注釋說明該閾值是“經(jīng)驗性地選取到足以避免在特定客戶數(shù)據(jù)庫上超時”的值。理解這三點后本次變更的五項新支持就不再是“功能列表”而是格上每一類算術(shù)/控制流算子的邊界傳播規(guī)則被逐一補全的過程。3. 新支持語法逐一對照源碼3.1 無符號數(shù)乘法下界相乘、上界相乘無符號乘法之所以值得單獨建模是因為它的邊界傳播比有符號乘法更簡單——兩個操作數(shù)都非負所以“下界×下界、上界×上界”就是精確答案不存在符號翻轉(zhuǎn)問題。源碼中UnsignedMulExpr類要求結(jié)果類型是IntegralType且無符號并刻意排除已按常量乘處理的表達式以避免重疊SimpleRangeAnalysis.qllprivate class UnsignedMulExpr extends MulExpr { UnsignedMulExpr() { this.getType().(IntegralType).isUnsigned() and // Avoid overlap. It should be slightly cheaper to analyze // MulByConstantExpr. not this instanceof MulByConstantExpr } }對應地getLowerBoundsImpl對UnsignedMulExpr取xLow * yLowgetUpperBoundsImpl取xHigh * yHighSimpleRangeAnalysis.qll 與 L1352-L1357。x * y形式的UnsignedAssignMulExpr也按同樣規(guī)則處理。變更前后對比的意義在于此前遇到unsigned乘法時表達式會落入“不可分析”分支下界直接退化為exprMinVal、上界退化為exprMaxVal所有依賴精確邊界的下游判斷都會失效現(xiàn)在這條路徑能給出真實邊界。3.2 與常量相乘把符號與量級分離處理“乘以一個常量”被拆成了四個協(xié)作的謂詞/類核心思想是乘正數(shù)與乘負數(shù)對上下界的作用是相反的必須分開傳播。MulByConstantExprSimpleRangeAnalysis.qll恰好一個操作數(shù)是常量的乘法表達式暴露出常量值getConstant()與非常量操作數(shù)getOperand()effectivelyMultipliesByPositive/effectivelyMultipliesByNegativeSimpleRangeAnalysis.qll除直接乘法外還覆蓋“等效”乘常量的情形——一元x乘 1、一元-x乘 -1、逗號表達式取右操作數(shù)、StmtExpr取結(jié)果表達式這些是真實 C/C 代碼里常見的慣用法AssignMulByConstantExpr及其正/負子類的劃分用于處理x * c。邊界傳播規(guī)則體現(xiàn)在getLowerBoundsImpl/getUpperBoundsImpl中乘正數(shù)時下界 常量 × 操作數(shù)下界上界 常量 × 操作數(shù)上界乘負數(shù)時上下界交換來源用操作數(shù)的上界算下界、下界算上界。這套規(guī)則同樣是x * c復合賦值語句的基礎。3.3 引用類型函數(shù)參數(shù)變更記錄列出的第三項是“引用類型函數(shù)參數(shù)”的支持。從當前源碼結(jié)構(gòu)看范圍分析統(tǒng)一經(jīng)由 SSA 信息工作變量訪問e只要能在RangeSsaDefinition中找到對應定義e def.getAUse(v)即 analyzableExpr 中“允許變量訪問前提是它有 SSA 信息”這一分支就可以通過getDefLowerBounds/getDefUpperBounds拿到邊界。引用類型參數(shù)在底層同樣有 SSA 定義可以推斷該項改進正是讓這類定義進入可分析集合的結(jié)果——具體到邊界傳播與按值參數(shù)走的是同一套規(guī)則。3.4 “不等于端點”收窄范圍不等比較的 phi 節(jié)點第四項“比較變量不等于其值域端點從而把范圍收窄一格”對應源碼中的isNEPhi機制。getPhiLowerBounds中有一段精確實現(xiàn)了這個語義SimpleRangeAnalysis.qllexists(VariableAccess access, float neConstant, float lower | isNEPhi(v, phi, access, neConstant) and lower getTruncatedLowerBounds(access) and if lower neConstant then result lower 1 else result lower )含義是如果在某個分支上已知x ! c而該分支入口處x的下界恰好就是c那么在這個分支里x的下界可以推進到c 1。上界方向?qū)ΨQ處理。這正是“narrowing the range by one”的出處它對循環(huán)不變量、數(shù)組下標驗證這類場景尤為有用。3.5if (x)/if (!x)的判零語義第五項支持的是布爾上下文中“非零即真”的語義。C/C 中if (x)、!x、邏輯運算、(bool)x都隱式測試x 0。實現(xiàn)位于boolConversionLowerBound/boolConversionUpperBoundSimpleRangeAnalysis.qll下界若expr的值域覆蓋 0下界為 0若能證明值域不含 0下界 0 或上界 0下界為 1若類型非算術(shù)類型如指針下界保守取 0上界若值域可能為 0上界取 0 與 1 都可能只有能證明“永遠非零”下界 0 或上界 0時上界才確定為 1反之能證明“永遠為零”時上界為 0。exprIsUsedAsBool謂詞SimpleRangeAnalysis.qll先把“會被當作布爾用”的表達式集合圈定下來——邏輯運算的子表達式、一元邏輯操作數(shù)、條件表達式條件、bool轉(zhuǎn)換——以避免對無關(guān)表達式做無謂的邊界計算。這個機制讓分析器能理解“進入if (x)分支意味著x ! 0、進入if (!x)分支意味著x 0”并據(jù)此在分支內(nèi)收窄后續(xù)表達式。4. 自定義規(guī)則擴展機制SimpleRangeAnalysisExpr 與官方示例本次變更的另一半是開放擴展點。抽象接口定義在 SimpleRangeAnalysisExpr.qll/** * An expression for which a range can be deduced. Extend this class to add * functionality to the range analysis library. */ abstract class SimpleRangeAnalysisExpr extends Expr { /** Gets the lower bound of the expression. */ abstract float getLowerBounds(); /** Gets the upper bound of the expression. */ abstract float getUpperBounds(); /** * Holds if the range this expression depends on the definition srcDef * for StackVariable srcVar. ... */ predicate dependsOnDef(RangeSsaDefinition srcDef, StackVariable srcVar) { none() } /** * Holds if this expression depends on the range of its unconverted * subexpression child. ... * For example, when modeling a function call whose return value depends on * all of its arguments, implement this predicate as * child this.getAnArgument(). */ abstract predicate dependsOnChild(Expr child); }實現(xiàn)一個擴展規(guī)則需要讓自定義類同時繼承SimpleRangeAnalysisExpr和具體的Expr子類如FunctionCall、SubExpr用類匹配條件圈定要建模的表達式覆寫getLowerBounds()/getUpperBounds()其中對子表達式取邊界時必須通過getFullyConvertedLowerBounds/getFullyConvertedUpperBounds遞歸注釋明確要求覆寫dependsOnChild(Expr child)聲明依賴了哪些未轉(zhuǎn)換子表達式的范圍——注釋特別強調(diào)不聲明周期依賴會導致“簡單情況能跑、復雜代碼上無限循環(huán)”。主庫 SimpleRangeAnalysis.qll 在上下界計算的最后一支統(tǒng)一調(diào)用SimpleRangeAnalysisExpr的getLowerBounds()/getUpperBounds()且內(nèi)置的邊界傳播規(guī)則明確以not expr instanceof SimpleRangeAnalysisExpr收尾即用戶擴展優(yōu)先于內(nèi)置規(guī)則且不同擴展類之間互不干擾。變更記錄中提到的示例目錄現(xiàn)路徑為 extensions 目錄給出了兩個可以直接參照的最小實現(xiàn)StrlenLiteralRangeExpr.qll對字面量字符串的strlen調(diào)用返回精確常量范圍——getLowerBounds與getUpperBounds都等于字符串字面量長度dependsOnChild返回none()因為范圍不依賴任何子表達式SubtractSelf.qll匹配x - x要求兩側(cè)顯式轉(zhuǎn)換后是同一個變量的訪問排除myInt - (unsigned char)myInt這類類型不同的情形上下界都返回 0。該目錄還有ConstantBitwiseAndExprRange.qll、ConstantShiftExprRange.qll、RangeNode.qll等更多示例覆蓋了“子表達式為常量時結(jié)果可精確推斷”這一最常見的擴展模式。5. 對下游查詢的影響與驗證路徑變更記錄說明這些改進“主要影響”三個查詢它們在倉庫中的位置與當前狀態(tài)可以逐一核對cpp/comparison-with-wider-type實現(xiàn)在 ComparisonWithWiderType.qlid與name見文件頭 L1-L15直接import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysisL20。窄類型與寬類型在循環(huán)條件中比較的問題其判定質(zhì)量直接取決于范圍分析能否給出循環(huán)變量的精確邊界cpp/integer-multiplication-cast-to-long對應 IntMultToLong.ql同樣構(gòu)建在SimpleRangeAnalysis之上。整數(shù)乘法結(jié)果轉(zhuǎn)換到long是否安全的判斷本質(zhì)上是“乘法上界是否落在 long 可表示范圍內(nèi)”的范圍判斷——無符號乘法與常量乘法的支持使這類判斷從保守退化變?yōu)榫_cpp/constant-comparison比較雙方是否恒為常量或恒定大小關(guān)系的判定依賴上下界是否收斂為同一點因此五項新支持全部都會提升它的判定率。除這三個查詢外當前倉庫中SnprintfOverflow.ql、OverflowStatic.ql、ImproperArrayIndexValidation.ql、InconsistentLoopDirection.ql等也都在SimpleRangeAnalysis之上構(gòu)建屬于同一能力的受益面。庫本身的回歸測試位于 SimpleRangeAnalysis_tests.cpp可作為理解每類構(gòu)造預期邊界的參考。6. 小結(jié)這次變更解決的核心問題回到變更記錄本身它解決的其實是兩個層面的問題。第一層是精度——無符號乘法、常量乘法、引用參數(shù)、NE 收窄、布爾判零這五類構(gòu)造補全后C 代碼中大量原本落入“不可分析→邊界退化為類型全范圍”的表達式開始產(chǎn)生精確邊界直接改善了三個核心查詢的查全率與查準率。第二層是可擴展性——SimpleRangeAnalysisExpr把“我知道這個表達式的范圍”從庫的內(nèi)置知識變成可注入的領(lǐng)域知識擴展者只需回答三個問題這個表達式是什么、它的上下界是多少、它依賴哪些子表達式的范圍。對基于 CodeQL 編寫 C 自定義查詢的開發(fā)者而言這套機制是向范圍分析庫貢獻項目特有算術(shù)語義的標準入口。贊分享靜態(tài)分析SAST應用安全漏洞掃描代碼質(zhì)量【免費下載鏈接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security項目地址https://gitcode.com/gh_mirrors/co/codeql點擊查看免費下載相關(guān)推薦Alex.js高級用法自定義規(guī)則和擴展檢測范圍的完整教程Alex.js高級用法自定義規(guī)則和擴展檢測范圍的完整教程 Alex.js是一個強大的敏感語言檢測工具能夠幫助開發(fā)者發(fā)現(xiàn)寫作中的不敏感、不周到表達。在前100開發(fā)工具LintFoundry 符號執(zhí)行改進無分支飽和乘法與 checked-multiply guard 的形式化證明Foundry 符號執(zhí)行改進無分支飽和乘法與 checked multiply guard 的形式化證明 本篇文章基于 Foundry 倉庫 .changel區(qū)塊鏈開發(fā)工具一文讀懂SAM 3D BodyMeta最新3D人體網(wǎng)格恢復技術(shù)如何突破遮擋與復雜視角難題一文讀懂SAM 3D BodyMeta最新3D人體網(wǎng)格恢復技術(shù)如何突破遮擋與復雜視角難題 SAM 3D Body是Meta推出的革命性3D人體網(wǎng)格恢復技術(shù)能上一篇如何通過Thorium瀏覽器獲得3大性能優(yōu)勢終極編譯優(yōu)化與隱私保護指南下一篇告別亂碼5分鐘掌握GBK到UTF-8編碼轉(zhuǎn)換的必備技巧創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考