|
1 | | -// Copyright (c) Microsoft Corporation. |
2 | | -// Licensed under the MIT license. |
3 | | -/** |
4 | | - * @name Return value not examined (C28193) |
5 | | - * @id cpp/drivers/examined-value |
6 | | - * @kind problem |
7 | | - * @description The returned value is annotated with the _Check_return_ or _Must_inspect_result_ annotation, but the calling function is either not using the value or is overwriting the value without examining it. |
8 | | - * @platform Desktop |
9 | | - * @security.severity Low |
10 | | - * @feature.area Multiple |
11 | | - * @impact Attack Surface Reduction |
12 | | - * @repro.text The following code location calls a function annotated with _Check_return_ or _Must_inspect_result_ but does not check the returned value. |
13 | | - * @owner.email sdat@microsoft.com |
14 | | - * @opaqueid CQLD-C28134 |
15 | | - * @problem.severity warning |
16 | | - * @precision high |
17 | | - * @tags correctness |
18 | | - * wddst |
19 | | - * @scope general |
20 | | - * @query-version v1 |
21 | | - */ |
22 | | - |
23 | | -import cpp |
24 | | -import drivers.libraries.SAL |
25 | | - |
26 | | -/** A function that is annotated with either _Check_return_ or _Must_inspect_result_. */ |
27 | | -class ReturnMustBeCheckedFunction extends Function { |
28 | | - SALCheckReturn scr; |
29 | | - |
30 | | - ReturnMustBeCheckedFunction() { this.getADeclarationEntry() = scr.getDeclarationEntry() } |
31 | | -} |
32 | | - |
33 | | -/** A function call to a function annotated with either _Check_return_ or _Must_inspect_result_. */ |
34 | | -class ReturnMustBeCheckedFunctionCall extends FunctionCall { |
35 | | - ReturnMustBeCheckedFunctionCall() { this.getTarget() instanceof ReturnMustBeCheckedFunction } |
36 | | -} |
37 | | - |
38 | | -/** Holds if an expression (a call to ReturnMustBeCheckedFunction in this case) is occuring in a void context. */ |
39 | | -predicate unUsed(Expr e) { |
40 | | - e instanceof ExprInVoidContext |
41 | | - or |
42 | | - definition(_, e.getParent()) and |
43 | | - not definitionUsePair(_, e.getParent(), _) |
44 | | -} |
45 | | - |
46 | | -/** |
47 | | - * Returns true if a ReturnMustBeCheckedFunction has its return value checked more than 75% of the time. |
48 | | - */ |
49 | | -predicate callFrequency(ReturnMustBeCheckedFunction f, string message) { |
50 | | - exists(Options opts, int used, int total, int percentage | |
51 | | - used = |
52 | | - count(ReturnMustBeCheckedFunctionCall fc | |
53 | | - fc.getTarget() = f and not opts.okToIgnoreReturnValue(fc) and not unUsed(fc) |
54 | | - ) and |
55 | | - total = |
56 | | - count(ReturnMustBeCheckedFunctionCall fc | |
57 | | - fc.getTarget() = f and not opts.okToIgnoreReturnValue(fc) |
58 | | - ) and |
59 | | - used != total and |
60 | | - percentage = used * 100 / total and |
61 | | - percentage >= 75 and |
62 | | - message = |
63 | | - percentage.toString() + |
64 | | - "% of calls to this function have their result checked. Checked return values = " + |
65 | | - used.toString() + " total calls = " + total.toString() |
66 | | - ) |
67 | | -} |
68 | | - |
69 | | -from ReturnMustBeCheckedFunctionCall unused, string message |
70 | | -where |
71 | | - unUsed(unused) and |
72 | | - not exists(Options opts | opts.okToIgnoreReturnValue(unused)) and |
73 | | - callFrequency(unused.getTarget(), message) and |
74 | | - not unused.getTarget().getName().matches("operator%") // exclude user defined operators |
75 | | -select unused, "Result of call to " + unused.getTarget().getName() + " is ignored; " + message |
| 1 | +// Copyright (c) Microsoft Corporation. |
| 2 | +// Licensed under the MIT license. |
| 3 | +/** |
| 4 | + * @name Return value not examined (C28193) |
| 5 | + * @id cpp/drivers/examined-value |
| 6 | + * @kind problem |
| 7 | + * @description The returned value is annotated with the _Check_return_ or _Must_inspect_result_ annotation, but the calling function is either not using the value or is overwriting the value without examining it. |
| 8 | + * @platform Desktop |
| 9 | + * @security.severity Low |
| 10 | + * @feature.area Multiple |
| 11 | + * @impact Attack Surface Reduction |
| 12 | + * @repro.text The following code location calls a function annotated with _Check_return_ or _Must_inspect_result_ but does not check the returned value. |
| 13 | + * @owner.email sdat@microsoft.com |
| 14 | + * @opaqueid CQLD-C28193 |
| 15 | + * @problem.severity warning |
| 16 | + * @precision high |
| 17 | + * @tags correctness |
| 18 | + * wddst |
| 19 | + * @scope general |
| 20 | + * @query-version v1 |
| 21 | + */ |
| 22 | + |
| 23 | +import cpp |
| 24 | +import drivers.libraries.SAL |
| 25 | + |
| 26 | +/** A function that is annotated with either _Check_return_ or _Must_inspect_result_. */ |
| 27 | +class ReturnMustBeCheckedFunction extends Function { |
| 28 | + SALCheckReturn scr; |
| 29 | + |
| 30 | + ReturnMustBeCheckedFunction() { this.getADeclarationEntry() = scr.getDeclarationEntry() } |
| 31 | +} |
| 32 | + |
| 33 | +/** A function call to a function annotated with either _Check_return_ or _Must_inspect_result_. */ |
| 34 | +class ReturnMustBeCheckedFunctionCall extends FunctionCall { |
| 35 | + ReturnMustBeCheckedFunctionCall() { this.getTarget() instanceof ReturnMustBeCheckedFunction } |
| 36 | +} |
| 37 | + |
| 38 | +/** Holds if an expression (a call to ReturnMustBeCheckedFunction in this case) is occuring in a void context. */ |
| 39 | +predicate unUsed(Expr e) { |
| 40 | + e instanceof ExprInVoidContext |
| 41 | + or |
| 42 | + definition(_, e.getParent()) and |
| 43 | + not definitionUsePair(_, e.getParent(), _) |
| 44 | +} |
| 45 | + |
| 46 | +/** |
| 47 | + * Returns true if a ReturnMustBeCheckedFunction has its return value checked more than 75% of the time. |
| 48 | + */ |
| 49 | +predicate callFrequency(ReturnMustBeCheckedFunction f, string message) { |
| 50 | + exists(Options opts, int used, int total, int percentage | |
| 51 | + ( |
| 52 | + used = |
| 53 | + count(ReturnMustBeCheckedFunctionCall fc | |
| 54 | + fc.getTarget() = f and not opts.okToIgnoreReturnValue(fc) and not unUsed(fc) |
| 55 | + ) and |
| 56 | + total = |
| 57 | + count(ReturnMustBeCheckedFunctionCall fc | |
| 58 | + fc.getTarget() = f and not opts.okToIgnoreReturnValue(fc) |
| 59 | + ) |
| 60 | + ) and |
| 61 | + ( |
| 62 | + used != total and |
| 63 | + percentage = used * 100 / total and |
| 64 | + percentage >= 75 and |
| 65 | + message = |
| 66 | + percentage.toString() + |
| 67 | + "% of calls to this function have their result checked. Checked return values = " + |
| 68 | + used.toString() + " total calls = " + total.toString() |
| 69 | + ) |
| 70 | + ) |
| 71 | +} |
| 72 | + |
| 73 | +from ReturnMustBeCheckedFunctionCall unused, string message |
| 74 | +where |
| 75 | + unUsed(unused) and |
| 76 | + not exists(Options opts | opts.okToIgnoreReturnValue(unused)) and |
| 77 | + callFrequency(unused.getTarget(), message) and |
| 78 | + not unused.getTarget().getName().matches("operator%") // exclude user defined operators |
| 79 | +select unused, "Result of call to " + unused.getTarget().getName() + " is ignored; " + message |
0 commit comments