1+ /**
2+ * @name Cast between semantically different integer types: HRESULT to/from a Boolean type
3+ * @description Cast between semantically different integer types: HRESULT to/from a Boolean type.
4+ * Boolean types indicate success by a non-zero value, whereas success (S_OK) in HRESULT is indicated by a value of 0.
5+ * Casting an HRESULT to/from a Boolean type and then using it in a test expression will yield an incorrect result.
6+ * @kind problem
7+ * @id cpp/hresult-boolean-conversion
8+ * @problem.severity error
9+ * @precision high
10+ * @tags security
11+ * external/cwe/cwe-253
12+ * external/microsoft/C6214
13+ * external/microsoft/C6215
14+ * external/microsoft/C6216
15+ * external/microsoft/C6217
16+ * external/microsoft/C6230
17+ */
18+ import cpp
19+
20+ predicate isHresultBooleanConverted ( Expr e1 , Cast e2 )
21+ {
22+ exists ( Type t1 , Type t2 |
23+ t1 = e1 .getType ( ) and
24+ t2 = e2 .getType ( ) and
25+ ( ( t1 .hasName ( "bool" ) or t1 .hasName ( "BOOL" ) or t1 .hasName ( "_Bool" ) ) and t2 .hasName ( "HRESULT" ) or
26+ ( t2 .hasName ( "bool" ) or t2 .hasName ( "BOOL" ) or t2 .hasName ( "_Bool" ) ) and t1 .hasName ( "HRESULT" )
27+ ) )
28+ }
29+
30+ predicate isHresultBooleanConverted ( Expr e1 )
31+ {
32+ exists ( Cast e2 |
33+ e2 = e1 .getConversion ( ) and
34+ isHresultBooleanConverted ( e1 , e2 )
35+ )
36+ }
37+
38+ from Expr e1 , string msg
39+ where exists
40+ (
41+ Cast e2 |
42+ e2 = e1 .getConversion ( ) |
43+ isHresultBooleanConverted ( e1 , e2 )
44+ and if e2 .isImplicit ( ) then ( msg = "Implicit conversion from " + e1 .getType ( ) .toString ( ) + " to " + e2 .getType ( ) .toString ( ) )
45+ else ( msg = "Explicit conversion from " + e1 .getType ( ) .toString ( ) + " to " + e2 .getType ( ) .toString ( ) )
46+ )
47+ or exists
48+ (
49+ ControlStructure ctls |
50+ ctls .getControllingExpr ( ) = e1
51+ and e1 .getType ( ) .( TypedefType ) .hasName ( "HRESULT" )
52+ and not isHresultBooleanConverted ( e1 )
53+ and msg = "Direct usage of a type " + e1 .getType ( ) .toString ( ) + " as a conditional expression"
54+ )
55+ or
56+ (
57+ exists ( BinaryLogicalOperation blop |
58+ blop .getAnOperand ( ) = e1 |
59+ e1 .getType ( ) .( TypedefType ) .hasName ( "HRESULT" )
60+ and msg = "Usage of a type " + e1 .getType ( ) .toString ( ) + " as an argument of a binary logical operation"
61+ )
62+ or exists
63+ (
64+ UnaryLogicalOperation ulop |
65+ ulop .getAnOperand ( ) = e1 |
66+ e1 .getType ( ) .( TypedefType ) .hasName ( "HRESULT" )
67+ and msg = "Usage of a type " + e1 .getType ( ) .toString ( ) + " as an argument of a unary logical operation"
68+ )
69+ and not isHresultBooleanConverted ( e1 )
70+ )
71+ select e1 , msg
0 commit comments