Skip to content

Commit 03d6b15

Browse files
committed
Merge branch 'main' into aeisenberg/pack/cpp
2 parents 88ceb42 + 88372df commit 03d6b15

File tree

273 files changed

+9831
-3091
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

273 files changed

+9831
-3091
lines changed

cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,5 @@ where
163163
or
164164
eots.dangerousCrementChanges()
165165
)
166-
select eots, "This expression may have undefined behavior."
166+
select eots,
167+
"This expression may have undefined behavior, because the order of evaluation is not specified."
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
| test.c:13:10:13:21 | call to tmpFunction1 | This expression may have undefined behavior. |
2-
| test.c:13:30:13:41 | call to tmpFunction2 | This expression may have undefined behavior. |
3-
| test.c:16:15:16:20 | ... ++ | This expression may have undefined behavior. |
1+
| test.c:13:10:13:21 | call to tmpFunction1 | This expression may have undefined behavior, because the order of evaluation is not specified. |
2+
| test.c:13:30:13:41 | call to tmpFunction2 | This expression may have undefined behavior, because the order of evaluation is not specified. |
3+
| test.c:16:15:16:20 | ... ++ | This expression may have undefined behavior, because the order of evaluation is not specified. |
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
typedef unsigned char uint8_t;
2+
#define SIZE (32)
3+
4+
void test_buffer_overrun_in_for_loop()
5+
{
6+
uint8_t data[SIZE] = {0};
7+
for (int x = 0; x < SIZE * 2; x++) {
8+
data[x] = 0x41; // BAD [NOT DETECTED]
9+
}
10+
}
11+
12+
void test_buffer_overrun_in_while_loop_using_pointer_arithmetic()
13+
{
14+
uint8_t data[SIZE] = {0};
15+
int offset = 0;
16+
while (offset < SIZE * 2) {
17+
*(data + offset) = 0x41; // BAD [NOT DETECTED]
18+
offset++;
19+
}
20+
}
21+
22+
void test_buffer_overrun_in_while_loop_using_array_indexing()
23+
{
24+
uint8_t data[SIZE] = {0};
25+
int offset = 0;
26+
while (offset < SIZE * 2) {
27+
data[offset] = 0x41; // BAD [NOT DETECTED]
28+
offset++;
29+
}
30+
}
31+
32+
int main(int argc, char *argv[])
33+
{
34+
test_buffer_overrun_in_for_loop();
35+
test_buffer_overrun_in_while_loop_using_pointer_arithmetic();
36+
test_buffer_overrun_in_while_loop_using_array_indexing();
37+
38+
return 0;
39+
}

cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void test6(bool cond)
114114

115115
c = 100;
116116
buffer[c] = 'x'; // BAD: over-write [NOT DETECTED]
117-
ch = buffer[c]; // BAD: under-read [NOT DETECTED]
117+
ch = buffer[c]; // BAD: over-read [NOT DETECTED]
118118

119119
d = 0;
120120
d = 1000;

csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -482,22 +482,6 @@ private static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, C
482482
{
483483
trapFile.Write(TrapExtensions.EncodeString(namedType.Name));
484484
}
485-
486-
if (namedType.IsGenericType && namedType.TypeKind != TypeKind.Error && namedType.TypeArguments.Any())
487-
{
488-
trapFile.Write('<');
489-
trapFile.BuildList(
490-
",",
491-
namedType.TypeArguments,
492-
p =>
493-
{
494-
if (IsReallyBound(namedType))
495-
{
496-
p.BuildDisplayName(cx, trapFile);
497-
}
498-
});
499-
trapFile.Write('>');
500-
}
501485
}
502486

503487
public static bool IsReallyUnbound(this INamedTypeSymbol type) =>

csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ it may be necessary to use a different deserialization framework.</p>
2727

2828
<sample src="UnsafeDeserializationUntrustedInputGood.cs" />
2929

30+
<p>In the following example potentially untrusted stream and type is deserialized using a
31+
<code>DataContractJsonSerializer</code> which is known to be vulnerable with user supplied types.</p>
32+
33+
<sample src="UnsafeDeserializationUntrustedInputTypeBad.cs" />
34+
35+
<p>To fix this specific vulnerability, we are using hardcoded
36+
Plain Old CLR Object (<a href="https://en.wikipedia.org/wiki/Plain_old_CLR_object">POCO</a>) type. In other cases,
37+
it may be necessary to use a different deserialization framework.</p>
38+
39+
<sample src="UnsafeDeserializationUntrustedInputTypeGood.cs" />
40+
3041
</example>
3142
<references>
3243

csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,46 @@ import csharp
1515
import semmle.code.csharp.security.dataflow.UnsafeDeserializationQuery
1616
import DataFlow::PathGraph
1717

18-
from TaintTrackingConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
19-
where config.hasFlowPath(source, sink)
20-
select sink.getNode(), source, sink, "$@ flows to unsafe deserializer.", source.getNode(),
21-
"User-provided data"
18+
from DataFlow::PathNode userInput, DataFlow::PathNode deserializeCallArg
19+
where
20+
exists(TaintToObjectMethodTrackingConfig taintTracking |
21+
// all flows from user input to deserialization with weak and strong type serializers
22+
taintTracking.hasFlowPath(userInput, deserializeCallArg)
23+
) and
24+
// intersect with strong types, but user controlled or weak types deserialization usages
25+
(
26+
exists(
27+
DataFlow::Node weakTypeCreation, DataFlow::Node weakTypeUsage,
28+
WeakTypeCreationToUsageTrackingConfig weakTypeDeserializerTracking, MethodCall mc
29+
|
30+
weakTypeDeserializerTracking.hasFlow(weakTypeCreation, weakTypeUsage) and
31+
mc.getQualifier() = weakTypeUsage.asExpr() and
32+
mc.getAnArgument() = deserializeCallArg.getNode().asExpr()
33+
)
34+
or
35+
exists(
36+
TaintToObjectTypeTrackingConfig userControlledTypeTracking, DataFlow::Node taintedTypeUsage,
37+
DataFlow::Node userInput2, MethodCall mc
38+
|
39+
userControlledTypeTracking.hasFlow(userInput2, taintedTypeUsage) and
40+
mc.getQualifier() = taintedTypeUsage.asExpr() and
41+
mc.getAnArgument() = deserializeCallArg.getNode().asExpr()
42+
)
43+
)
44+
or
45+
// no type check needed - straightforward taint -> sink
46+
exists(TaintToConstructorOrStaticMethodTrackingConfig taintTracking2 |
47+
taintTracking2.hasFlowPath(userInput, deserializeCallArg)
48+
)
49+
or
50+
// JsonConvert static method call, but with additional unsafe typename tracking
51+
exists(
52+
JsonConvertTrackingConfig taintTrackingJsonConvert, TypeNameTrackingConfig typenameTracking,
53+
DataFlow::Node settingsCallArg
54+
|
55+
taintTrackingJsonConvert.hasFlowPath(userInput, deserializeCallArg) and
56+
typenameTracking.hasFlow(_, settingsCallArg) and
57+
deserializeCallArg.getNode().asExpr().getParent() = settingsCallArg.asExpr().getParent()
58+
)
59+
select deserializeCallArg, userInput, deserializeCallArg, "$@ flows to unsafe deserializer.",
60+
userInput, "User-provided data"

csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputGood.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class Good
66
public static object Deserialize(TextBox textBox)
77
{
88
JavaScriptSerializer sr = new JavaScriptSerializer();
9-
// GOOD
9+
// GOOD: no unsafe type resolver
1010
return sr.DeserializeObject(textBox.Text);
1111
}
1212
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Runtime.Serialization.Json;
2+
using System.IO;
3+
using System;
4+
5+
class BadDataContractJsonSerializer
6+
{
7+
public static object Deserialize(string type, Stream s)
8+
{
9+
// BAD: stream and type are potentially untrusted
10+
var ds = new DataContractJsonSerializer(Type.GetType(type));
11+
return ds.ReadObject(s);
12+
}
13+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Runtime.Serialization.Json;
2+
using System.IO;
3+
using System;
4+
5+
class Poco
6+
{
7+
public int Count;
8+
9+
public string Comment;
10+
}
11+
12+
class GoodDataContractJsonSerializer
13+
{
14+
public static Poco Deserialize(Stream s)
15+
{
16+
// GOOD: while stream is potentially untrusted, the instantiated type is hardcoded
17+
var ds = new DataContractJsonSerializer(typeof(Poco));
18+
return (Poco)ds.ReadObject(s);
19+
}
20+
}

0 commit comments

Comments
 (0)