Skip to content

Commit 0f8f96c

Browse files
committed
Adding IncorrectUsageOfRtlCompareMemory.qhelp, ql and example files.
1 parent 7edf552 commit 0f8f96c

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p><code>RtlCompareMemory</code> routine compares two blocks of memory and returns the number of bytes that match, not a boolean value indicating a full comparison like <code>RtlEqualMemory</code> does.</p>
7+
<p>This query detects the return value of <code>RtlCompareMemory</code> being handled as a boolean.</p>
8+
</overview>
9+
10+
<recommendation>
11+
<p>Any findings from this rule may indicate that the return value of a call to <code>RtlCompareMemory</code> is being incorrectly interpreted as a boolean.</p>
12+
<p>Review the logic of the call, and if necessary, replace the function call with <code>RtlEqualMemory</code>.</p>
13+
</recommendation>
14+
15+
<example>
16+
<p>The following example is a typical one where an identity comparison is intended, but the wrong API is being used.</p>
17+
<sample src="IncorrectUsageOfRtlCompareMemoryBad.c" />
18+
19+
<p>In this example, the fix is to replace the call to <code>RtlCompareMemory</code> with <code>RtlEqualMemory</code>.</p>
20+
21+
<sample src="IncorrectUsageOfRtlCompareMemoryGood.c" />
22+
23+
</example>
24+
<references>
25+
<li>Books online <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlcomparememory">RtlCompareMemory function (wdm.h)</a></li>
26+
<li>Books online <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlequalmemory">RtlEqualMemory macro (wdm.h)</a></li>
27+
</references>
28+
29+
</qhelp>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @id cpp/drivers/incorrect-usage-of-rtlcomparememory
3+
* @name Incorrect usage of RtlCompareMemory
4+
* @description `RtlCompareMemory` routine compares two blocks of memory and returns the number of bytes that match, not a boolean value indicating a full comparison like `RtlEqualMemory` does.
5+
* This query detects the return value of `RtlCompareMemory` being handled as a boolean.
6+
* @security.severity Important
7+
* @kind problem
8+
* @problem.severity error
9+
* @precision high
10+
* @tags security
11+
* kernel
12+
*/
13+
14+
import cpp
15+
16+
predicate isLiteralABooleanMacro(Literal l) {
17+
exists(MacroInvocation mi | mi.getExpr() = l |
18+
mi.getMacroName() in ["true", "false", "TRUE", "FALSE"]
19+
)
20+
}
21+
22+
from FunctionCall fc, Function f, Expr e, string msg
23+
where
24+
f.getQualifiedName() = "RtlCompareMemory" and
25+
f.getACallToThisFunction() = fc and
26+
(
27+
exists(UnaryLogicalOperation ulo | e = ulo |
28+
ulo.getAnOperand() = fc and
29+
msg = "as an operand in an unary logical operation"
30+
)
31+
or
32+
exists(BinaryLogicalOperation blo | e = blo |
33+
blo.getAnOperand() = fc and
34+
msg = "as an operand in a binary logical operation"
35+
)
36+
or
37+
exists(Conversion conv | e = conv |
38+
(
39+
conv.getType().hasName("bool") or
40+
conv.getType().hasName("BOOLEAN") or
41+
conv.getType().hasName("_Bool")
42+
) and
43+
conv.getUnconverted() = fc and
44+
msg = "as a boolean"
45+
)
46+
or
47+
exists(IfStmt s | e = s.getControllingExpr() |
48+
s.getControllingExpr() = fc and
49+
msg = "as the controlling expression in an If statement"
50+
)
51+
or
52+
exists(EqualityOperation bao, Expr e2 | e = bao |
53+
bao.hasOperands(fc, e2) and
54+
isLiteralABooleanMacro(e2) and
55+
msg =
56+
"as an operand in an equality operation where the other operand is a boolean value (high precision result)"
57+
)
58+
or
59+
exists(EqualityOperation bao, Expr e2 | e = bao |
60+
bao.hasOperands(fc, e2) and
61+
(e2.(Literal).getValue().toInt() = 1 or e2.(Literal).getValue().toInt() = 0) and
62+
not isLiteralABooleanMacro(e2) and
63+
msg =
64+
"as an operand in an equality operation where the other operand is likely a boolean value (lower precision result, needs to be reviewed)"
65+
)
66+
)
67+
select e,
68+
"This $@ is being handled $@ instead of the number of matching bytes. Please review the usage of this function and consider replacing it with `RtlEqualMemory`.",
69+
fc, "call to `RtlCompareMemory`", e, msg
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//bug, the code assumes RtlCompareMemory is comparing for identical values & return false if not identical
2+
if (!RtlCompareMemory(pBuffer, ptr, 16))
3+
{
4+
return FALSE;
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//fixed
2+
if (!RtlEqualMemory(pBuffer, ptr, 16))
3+
{
4+
return FALSE;
5+
}

0 commit comments

Comments
 (0)