11/**
22 * @name Integer addition may overflow inside if statement
3- * @description Detects "if (a+b>c) a=c-b", which incorrectly implements
4- * a = min(a,c-b) if a+b overflows. Should be replaced by
5- * "if (a>c-b) a=c-b". Also detects "if (b+a>c) a=c-b"
6- * (swapped terms in addition), if (a+b>c) { a=c-b }"
7- * (assignment inside block), "c<a+b" (swapped operands) and
8- * ">=", "<", "<=" instead of ">" (all operators). This
9- * integer overflow is the root cause of the buffer overflow
3+ * @description Writing 'if (a+b>c) a=c-b' incorrectly implements
4+ * 'a = min(a,c-b)' if 'a+b' overflows. This integer
5+ * overflow is the root cause of the buffer overflow
106 * in the SHA-3 reference implementation (CVE-2022-37454).
117 * @kind problem
128 * @problem.severity warning
@@ -21,22 +17,26 @@ import cpp
2117import semmle.code.cpp.valuenumbering.GlobalValueNumbering
2218import semmle.code.cpp.valuenumbering.HashCons
2319import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
24- import semmle.code.cpp.commons.Exclusions
20+ import semmle.code.cpp.controlflow.Guards
2521
26- from IfStmt ifstmt , RelationalOperation relop , ExprStmt exprstmt , BlockStmt blockstmt , AssignExpr assignexpr , AddExpr addexpr , SubExpr subexpr
27- where ifstmt .getCondition ( ) = relop and
28- relop .getAnOperand ( ) = addexpr and
22+ from
23+ GuardCondition guard , Expr expr , ExprStmt exprstmt , BasicBlock block , AssignExpr assignexpr ,
24+ AddExpr addexpr , SubExpr subexpr
25+ where
26+ ( guard .ensuresLt ( expr , addexpr , 0 , block , _) or guard .ensuresLt ( addexpr , expr , 0 , block , _) ) and
2927 addexpr .getUnspecifiedType ( ) instanceof IntegralType and
30- not isFromMacroDefinition ( relop ) and
3128 exprMightOverflowPositively ( addexpr ) and
32- ( ifstmt .getThen ( ) = exprstmt or
33- ( ifstmt .getThen ( ) = blockstmt and
34- blockstmt .getAStmt ( ) = exprstmt ) ) and
29+ block .getANode ( ) = exprstmt and
3530 exprstmt .getExpr ( ) = assignexpr and
3631 assignexpr .getRValue ( ) = subexpr and
37- ( ( hashCons ( addexpr .getLeftOperand ( ) ) = hashCons ( assignexpr .getLValue ( ) ) and
38- globalValueNumber ( addexpr .getRightOperand ( ) ) = globalValueNumber ( subexpr .getRightOperand ( ) ) ) or
39- ( hashCons ( addexpr .getRightOperand ( ) ) = hashCons ( assignexpr .getLValue ( ) ) and
40- globalValueNumber ( addexpr .getLeftOperand ( ) ) = globalValueNumber ( subexpr .getRightOperand ( ) ) ) ) and
41- globalValueNumber ( relop .getAnOperand ( ) ) = globalValueNumber ( subexpr .getLeftOperand ( ) )
42- select ifstmt , "\"if (a+b>c) a=c-b\" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as \"if (a>c-b) a=c-b\" which avoids the overflow." , addexpr , "addition"
32+ (
33+ hashCons ( addexpr .getLeftOperand ( ) ) = hashCons ( assignexpr .getLValue ( ) ) and
34+ globalValueNumber ( addexpr .getRightOperand ( ) ) = globalValueNumber ( subexpr .getRightOperand ( ) )
35+ or
36+ hashCons ( addexpr .getRightOperand ( ) ) = hashCons ( assignexpr .getLValue ( ) ) and
37+ globalValueNumber ( addexpr .getLeftOperand ( ) ) = globalValueNumber ( subexpr .getRightOperand ( ) )
38+ ) and
39+ globalValueNumber ( expr ) = globalValueNumber ( subexpr .getLeftOperand ( ) )
40+ select guard ,
41+ "\"if (a+b>c) a=c-b\" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as \"if (a>c-b) a=c-b\" which avoids the overflow." ,
42+ addexpr , "addition"
0 commit comments