Skip to content

Commit 8cef798

Browse files
authored
Merge pull request github#13202 from michaelnebel/csharp/systemdatetimedefaults
C#: System.DateTime defaults.
2 parents 5c77ede + 2c37cb7 commit 8cef798

File tree

7 files changed

+171
-26
lines changed

7 files changed

+171
-26
lines changed

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ private static bool ContainsPattern(SyntaxNode node) =>
211211
return Default.CreateGenerated(cx, parent, childIndex, location, ValueAsString(null));
212212
}
213213

214+
if (type.SpecialType is SpecialType.System_DateTime)
215+
{
216+
return DateTimeObjectCreation.CreateGenerated(cx, parent, childIndex, type, defaultValue, location);
217+
}
218+
214219
// const literal:
215220
return Literal.CreateGenerated(cx, parent, childIndex, type, defaultValue, location);
216221
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using Microsoft.CodeAnalysis;
2+
using System.Linq;
3+
using System.IO;
4+
using Semmle.Extraction.Kinds;
5+
6+
namespace Semmle.Extraction.CSharp.Entities.Expressions
7+
{
8+
internal class DateTimeObjectCreation : Expression
9+
{
10+
private readonly IMethodSymbol constructorSymbol;
11+
12+
private DateTimeObjectCreation(IMethodSymbol constructorSymbol, ExpressionInfo info) : base(info)
13+
{
14+
this.constructorSymbol = constructorSymbol;
15+
}
16+
17+
// Gets the value of a System.DateTime object as a string containing the ticks.
18+
private static long ValueAsLong(object? value) =>
19+
value is System.DateTime d ? d.Ticks : 0;
20+
21+
// Gets the System.DateTime(long) constructor from the `type` symbol.
22+
private static IMethodSymbol? GetDateTimeConstructor(ITypeSymbol? type)
23+
{
24+
return type?.GetMembers()
25+
.Where(m =>
26+
m is IMethodSymbol c &&
27+
c.GetName() == "ctor" &&
28+
c.Parameters.Length == 1 &&
29+
c.Parameters[0].Type.SpecialType == SpecialType.System_Int64)
30+
.Cast<IMethodSymbol>()
31+
.FirstOrDefault();
32+
}
33+
34+
35+
protected void PopulateExpression(TextWriter trapFile)
36+
{
37+
var constructor = Constructor.Create(Context, constructorSymbol);
38+
trapFile.expr_call(this, constructor);
39+
}
40+
41+
protected new Expression TryPopulate()
42+
{
43+
Context.Try(null, null, () => PopulateExpression(Context.TrapWriter.Writer));
44+
return this;
45+
}
46+
47+
// Gets an expression that represents a System.DateTime object creation.
48+
// The `type` symbol must be a System.DateTime type and the value must be a System.DateTime object.
49+
// The expression that is being created is a call to the System.DateTime(long) constructor, where
50+
// the number of ticks from the `value` object is used as the argument to the constructor call.
51+
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, object? value, Extraction.Entities.Location location)
52+
{
53+
var constructorSymbol = GetDateTimeConstructor(type) ?? throw new InternalError("Could not find symbol for System.DateTime(long)");
54+
var expr = new DateTimeObjectCreation(constructorSymbol, new ExpressionInfo(
55+
cx,
56+
AnnotatedTypeSymbol.CreateNotAnnotated(type),
57+
location,
58+
ExprKind.OBJECT_CREATION,
59+
parent,
60+
childIndex,
61+
true,
62+
null));
63+
64+
var longTypeSymbol = constructorSymbol.Parameters[0].Type;
65+
Literal.CreateGenerated(cx, expr, 0, longTypeSymbol, ValueAsLong(value), location);
66+
67+
return expr.TryPopulate();
68+
}
69+
}
70+
}

csharp/ql/test/library-tests/parameters/Parameters.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Runtime.CompilerServices;
4+
15
public class Parameters
26
{
37
public void M1(int a, object b, string c) => throw null;
@@ -12,6 +16,16 @@ public class Parameters
1216
public void M9<T>(T t = default) where T : struct => throw null;
1317
public void M10<T>(T t = default) where T : class => throw null;
1418

19+
public void M11(int arg1 = 3) => throw null;
20+
public void M12(DateTime arg2 = default) => throw null;
21+
public void M13(DateTime? arg3 = null) => throw null;
22+
public void M14([Optional, DateTimeConstant(14L)] DateTime arg4) => throw null;
23+
public void M15([Optional, DateTimeConstant(10001L)] DateTime? arg5) => throw null;
24+
public void M16([Optional, DefaultParameterValue(6L)] long arg6) => throw null;
25+
public void M17([Optional, DefaultParameterValue(null)] object arg7) => throw null;
26+
public void M18([Optional, DefaultParameterValue(3)] int? arg8) => throw null;
27+
public void M19([Optional, DecimalConstant(1, 0, 0, 0, 103)] decimal arg9) => throw null;
28+
1529
public struct MyStruct { }
1630
public enum MyEnum { A = 1, B = 2 }
1731
}

csharp/ql/test/library-tests/parameters/Parameters.cs_

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Runtime.CompilerServices;
4+
15
public class ParametersDll
26
{
37
public void M1(int a, object b, string c) => throw null;
@@ -12,6 +16,16 @@ public class ParametersDll
1216
public void M9<T>(T t = default) where T : struct => throw null;
1317
public void M10<T>(T t = default) where T : class => throw null;
1418

19+
public void M11(int arg1 = 3) => throw null;
20+
public void M12(DateTime arg2 = default) => throw null;
21+
public void M13(DateTime? arg3 = null) => throw null;
22+
public void M14([Optional, DateTimeConstant(14L)] DateTime arg4) => throw null;
23+
public void M15([Optional, DateTimeConstant(10001L)] DateTime? arg5) => throw null;
24+
public void M16([Optional, DefaultParameterValue(6L)] long arg6) => throw null;
25+
public void M17([Optional, DefaultParameterValue(null)] object arg7) => throw null;
26+
public void M18([Optional, DefaultParameterValue(3)] int? arg8) => throw null;
27+
public void M19([Optional, DecimalConstant(1, 0, 0, 0, 103)] decimal arg9) => throw null;
28+
1529
public struct MyStruct { }
1630
public enum MyEnum { A = 1, B = 2 }
1731
}
Binary file not shown.
Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,44 @@
11
noDefaultValue
2-
| Parameters.cs:3:17:3:18 | M1 | Parameters.cs:3:24:3:24 | a | 0 |
3-
| Parameters.cs:3:17:3:18 | M1 | Parameters.cs:3:34:3:34 | b | 1 |
4-
| Parameters.cs:3:17:3:18 | M1 | Parameters.cs:3:44:3:44 | c | 2 |
5-
| Parameters.cs:4:17:4:18 | M2 | Parameters.cs:4:24:4:24 | a | 0 |
6-
| Parameters.cs:8:17:8:18 | M6 | Parameters.cs:8:29:8:30 | s1 | 0 |
7-
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:27:9:28 | e1 | 0 |
2+
| Parameters.cs:7:17:7:18 | M1 | Parameters.cs:7:24:7:24 | a | 0 |
3+
| Parameters.cs:7:17:7:18 | M1 | Parameters.cs:7:34:7:34 | b | 1 |
4+
| Parameters.cs:7:17:7:18 | M1 | Parameters.cs:7:44:7:44 | c | 2 |
5+
| Parameters.cs:8:17:8:18 | M2 | Parameters.cs:8:24:8:24 | a | 0 |
6+
| Parameters.cs:12:17:12:18 | M6 | Parameters.cs:12:29:12:30 | s1 | 0 |
7+
| Parameters.cs:13:17:13:18 | M7 | Parameters.cs:13:27:13:28 | e1 | 0 |
88
| Parameters.dll:0:0:0:0 | M1 | Parameters.dll:0:0:0:0 | a | 0 |
99
| Parameters.dll:0:0:0:0 | M1 | Parameters.dll:0:0:0:0 | b | 1 |
1010
| Parameters.dll:0:0:0:0 | M1 | Parameters.dll:0:0:0:0 | c | 2 |
1111
| Parameters.dll:0:0:0:0 | M2 | Parameters.dll:0:0:0:0 | a | 0 |
1212
| Parameters.dll:0:0:0:0 | M6 | Parameters.dll:0:0:0:0 | s1 | 0 |
1313
| Parameters.dll:0:0:0:0 | M7 | Parameters.dll:0:0:0:0 | e1 | 0 |
1414
withDefaultValue
15-
| Parameters.cs:4:17:4:18 | M2 | Parameters.cs:4:34:4:34 | b | 1 | Parameters.cs:4:38:4:41 | null | null |
16-
| Parameters.cs:4:17:4:18 | M2 | Parameters.cs:4:51:4:51 | c | 2 | Parameters.cs:4:55:4:70 | "default string" | default string |
17-
| Parameters.cs:5:17:5:18 | M3 | Parameters.cs:5:24:5:24 | a | 0 | Parameters.cs:5:28:5:28 | 1 | 1 |
18-
| Parameters.cs:5:17:5:18 | M3 | Parameters.cs:5:38:5:38 | b | 1 | Parameters.cs:5:42:5:45 | null | null |
19-
| Parameters.cs:5:17:5:18 | M3 | Parameters.cs:5:55:5:55 | c | 2 | Parameters.cs:5:59:5:64 | "null" | null |
20-
| Parameters.cs:6:17:6:18 | M4 | Parameters.cs:6:24:6:24 | a | 0 | Parameters.cs:6:28:6:34 | (...) ... | 0 |
21-
| Parameters.cs:6:17:6:18 | M4 | Parameters.cs:6:44:6:44 | b | 1 | Parameters.cs:6:48:6:54 | default | null |
22-
| Parameters.cs:7:17:7:18 | M5 | Parameters.cs:7:24:7:24 | a | 0 | Parameters.cs:7:28:7:36 | object creation of type Int32 | 0 |
23-
| Parameters.cs:7:17:7:18 | M5 | Parameters.cs:7:46:7:46 | b | 1 | Parameters.cs:7:50:7:56 | default | null |
24-
| Parameters.cs:8:17:8:18 | M6 | Parameters.cs:8:42:8:43 | s2 | 1 | Parameters.cs:8:47:8:63 | default(...) | - |
25-
| Parameters.cs:8:17:8:18 | M6 | Parameters.cs:8:75:8:76 | s3 | 2 | Parameters.cs:8:80:8:93 | object creation of type MyStruct | - |
26-
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:38:9:39 | e2 | 1 | Parameters.cs:9:43:9:57 | default(...) | 0 |
27-
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:67:9:68 | e3 | 2 | Parameters.cs:9:72:9:83 | object creation of type MyEnum | 0 |
28-
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:93:9:94 | e4 | 3 | Parameters.cs:9:98:9:105 | access to constant A | 1 |
29-
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:115:9:116 | e5 | 4 | Parameters.cs:9:120:9:128 | (...) ... | 5 |
30-
| Parameters.cs:11:17:11:21 | M8<> | Parameters.cs:11:25:11:25 | t | 0 | Parameters.cs:11:29:11:35 | (...) ... | - |
31-
| Parameters.cs:12:17:12:21 | M9<> | Parameters.cs:12:25:12:25 | t | 0 | Parameters.cs:12:29:12:35 | (...) ... | - |
32-
| Parameters.cs:13:17:13:22 | M10<> | Parameters.cs:13:26:13:26 | t | 0 | Parameters.cs:13:30:13:36 | (...) ... | null |
15+
| Parameters.cs:8:17:8:18 | M2 | Parameters.cs:8:34:8:34 | b | 1 | Parameters.cs:8:38:8:41 | null | null |
16+
| Parameters.cs:8:17:8:18 | M2 | Parameters.cs:8:51:8:51 | c | 2 | Parameters.cs:8:55:8:70 | "default string" | default string |
17+
| Parameters.cs:9:17:9:18 | M3 | Parameters.cs:9:24:9:24 | a | 0 | Parameters.cs:9:28:9:28 | 1 | 1 |
18+
| Parameters.cs:9:17:9:18 | M3 | Parameters.cs:9:38:9:38 | b | 1 | Parameters.cs:9:42:9:45 | null | null |
19+
| Parameters.cs:9:17:9:18 | M3 | Parameters.cs:9:55:9:55 | c | 2 | Parameters.cs:9:59:9:64 | "null" | null |
20+
| Parameters.cs:10:17:10:18 | M4 | Parameters.cs:10:24:10:24 | a | 0 | Parameters.cs:10:28:10:34 | (...) ... | 0 |
21+
| Parameters.cs:10:17:10:18 | M4 | Parameters.cs:10:44:10:44 | b | 1 | Parameters.cs:10:48:10:54 | default | null |
22+
| Parameters.cs:11:17:11:18 | M5 | Parameters.cs:11:24:11:24 | a | 0 | Parameters.cs:11:28:11:36 | object creation of type Int32 | 0 |
23+
| Parameters.cs:11:17:11:18 | M5 | Parameters.cs:11:46:11:46 | b | 1 | Parameters.cs:11:50:11:56 | default | null |
24+
| Parameters.cs:12:17:12:18 | M6 | Parameters.cs:12:42:12:43 | s2 | 1 | Parameters.cs:12:47:12:63 | default(...) | - |
25+
| Parameters.cs:12:17:12:18 | M6 | Parameters.cs:12:75:12:76 | s3 | 2 | Parameters.cs:12:80:12:93 | object creation of type MyStruct | - |
26+
| Parameters.cs:13:17:13:18 | M7 | Parameters.cs:13:38:13:39 | e2 | 1 | Parameters.cs:13:43:13:57 | default(...) | 0 |
27+
| Parameters.cs:13:17:13:18 | M7 | Parameters.cs:13:67:13:68 | e3 | 2 | Parameters.cs:13:72:13:83 | object creation of type MyEnum | 0 |
28+
| Parameters.cs:13:17:13:18 | M7 | Parameters.cs:13:93:13:94 | e4 | 3 | Parameters.cs:13:98:13:105 | access to constant A | 1 |
29+
| Parameters.cs:13:17:13:18 | M7 | Parameters.cs:13:115:13:116 | e5 | 4 | Parameters.cs:13:120:13:128 | (...) ... | 5 |
30+
| Parameters.cs:15:17:15:21 | M8<> | Parameters.cs:15:25:15:25 | t | 0 | Parameters.cs:15:29:15:35 | (...) ... | - |
31+
| Parameters.cs:16:17:16:21 | M9<> | Parameters.cs:16:25:16:25 | t | 0 | Parameters.cs:16:29:16:35 | (...) ... | - |
32+
| Parameters.cs:17:17:17:22 | M10<> | Parameters.cs:17:26:17:26 | t | 0 | Parameters.cs:17:30:17:36 | (...) ... | null |
33+
| Parameters.cs:19:17:19:19 | M11 | Parameters.cs:19:25:19:28 | arg1 | 0 | Parameters.cs:19:32:19:32 | 3 | 3 |
34+
| Parameters.cs:20:17:20:19 | M12 | Parameters.cs:20:30:20:33 | arg2 | 0 | Parameters.cs:20:37:20:43 | (...) ... | - |
35+
| Parameters.cs:21:17:21:19 | M13 | Parameters.cs:21:31:21:34 | arg3 | 0 | Parameters.cs:21:38:21:41 | null | null |
36+
| Parameters.cs:22:17:22:19 | M14 | Parameters.cs:22:64:22:67 | arg4 | 0 | Parameters.cs:22:21:22:67 | object creation of type DateTime | - |
37+
| Parameters.cs:23:17:23:19 | M15 | Parameters.cs:23:68:23:71 | arg5 | 0 | Parameters.cs:23:21:23:71 | object creation of type DateTime | - |
38+
| Parameters.cs:24:17:24:19 | M16 | Parameters.cs:24:64:24:67 | arg6 | 0 | Parameters.cs:24:21:24:67 | 6 | 6 |
39+
| Parameters.cs:25:17:25:19 | M17 | Parameters.cs:25:68:25:71 | arg7 | 0 | Parameters.cs:25:21:25:71 | default | null |
40+
| Parameters.cs:26:17:26:19 | M18 | Parameters.cs:26:63:26:66 | arg8 | 0 | Parameters.cs:26:21:26:66 | 3 | 3 |
41+
| Parameters.cs:27:17:27:19 | M19 | Parameters.cs:27:74:27:77 | arg9 | 0 | Parameters.cs:27:21:27:77 | 10.3 | 10.3 |
3342
| Parameters.dll:0:0:0:0 | M2 | Parameters.dll:0:0:0:0 | b | 1 | Parameters.dll:0:0:0:0 | default | null |
3443
| Parameters.dll:0:0:0:0 | M2 | Parameters.dll:0:0:0:0 | c | 2 | Parameters.dll:0:0:0:0 | "default string" | default string |
3544
| Parameters.dll:0:0:0:0 | M3 | Parameters.dll:0:0:0:0 | a | 0 | Parameters.dll:0:0:0:0 | 1 | 1 |
@@ -48,3 +57,17 @@ withDefaultValue
4857
| Parameters.dll:0:0:0:0 | M8<> | Parameters.dll:0:0:0:0 | t | 0 | Parameters.dll:0:0:0:0 | default | - |
4958
| Parameters.dll:0:0:0:0 | M9<> | Parameters.dll:0:0:0:0 | t | 0 | Parameters.dll:0:0:0:0 | default | - |
5059
| Parameters.dll:0:0:0:0 | M10<> | Parameters.dll:0:0:0:0 | t | 0 | Parameters.dll:0:0:0:0 | default | null |
60+
| Parameters.dll:0:0:0:0 | M11 | Parameters.dll:0:0:0:0 | arg1 | 0 | Parameters.dll:0:0:0:0 | 3 | 3 |
61+
| Parameters.dll:0:0:0:0 | M12 | Parameters.dll:0:0:0:0 | arg2 | 0 | Parameters.dll:0:0:0:0 | default | - |
62+
| Parameters.dll:0:0:0:0 | M13 | Parameters.dll:0:0:0:0 | arg3 | 0 | Parameters.dll:0:0:0:0 | default | - |
63+
| Parameters.dll:0:0:0:0 | M14 | Parameters.dll:0:0:0:0 | arg4 | 0 | Parameters.dll:0:0:0:0 | object creation of type DateTime | - |
64+
| Parameters.dll:0:0:0:0 | M15 | Parameters.dll:0:0:0:0 | arg5 | 0 | Parameters.dll:0:0:0:0 | object creation of type DateTime | - |
65+
| Parameters.dll:0:0:0:0 | M16 | Parameters.dll:0:0:0:0 | arg6 | 0 | Parameters.dll:0:0:0:0 | 6 | 6 |
66+
| Parameters.dll:0:0:0:0 | M17 | Parameters.dll:0:0:0:0 | arg7 | 0 | Parameters.dll:0:0:0:0 | default | null |
67+
| Parameters.dll:0:0:0:0 | M18 | Parameters.dll:0:0:0:0 | arg8 | 0 | Parameters.dll:0:0:0:0 | 3 | 3 |
68+
| Parameters.dll:0:0:0:0 | M19 | Parameters.dll:0:0:0:0 | arg9 | 0 | Parameters.dll:0:0:0:0 | 10.3 | 10.3 |
69+
dateTimeDefaults
70+
| Parameters.cs:22:17:22:19 | M14 | Parameters.cs:22:64:22:67 | arg4 | Parameters.cs:22:21:22:67 | object creation of type DateTime | DateTime(long) | 14 |
71+
| Parameters.cs:23:17:23:19 | M15 | Parameters.cs:23:68:23:71 | arg5 | Parameters.cs:23:21:23:71 | object creation of type DateTime | DateTime(long) | 10001 |
72+
| Parameters.dll:0:0:0:0 | M14 | Parameters.dll:0:0:0:0 | arg4 | Parameters.dll:0:0:0:0 | object creation of type DateTime | DateTime(long) | 14 |
73+
| Parameters.dll:0:0:0:0 | M15 | Parameters.dll:0:0:0:0 | arg5 | Parameters.dll:0:0:0:0 | object creation of type DateTime | DateTime(long) | 10001 |

csharp/ql/test/library-tests/parameters/Parameters.ql

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,35 @@ private predicate fromTestLocation(Element e) {
44
e.fromSource() or e.getFile().getStem() = "Parameters"
55
}
66

7+
private predicate compilerGeneratedAttribute(Parameterizable container) {
8+
container.getDeclaringType().getAnAttribute().getType().toStringWithTypes() =
9+
"CompilerGeneratedAttribute"
10+
}
11+
712
query predicate noDefaultValue(Parameterizable container, Parameter p, int i) {
813
fromTestLocation(container) and
914
not p.hasDefaultValue() and
10-
container.getParameter(i) = p
15+
container.getParameter(i) = p and
16+
not compilerGeneratedAttribute(container)
1117
}
1218

1319
query predicate withDefaultValue(Parameterizable container, Parameter p, int i, Expr e, string value) {
1420
fromTestLocation(container) and
1521
p.hasDefaultValue() and
1622
container.getParameter(i) = p and
1723
p.getDefaultValue() = e and
18-
if exists(e.getValue()) then value = e.getValue() else value = "-"
24+
(if exists(e.getValue()) then value = e.getValue() else value = "-") and
25+
not compilerGeneratedAttribute(container)
26+
}
27+
28+
query predicate dateTimeDefaults(
29+
Parameterizable container, Parameter p, ObjectCreation o, string constructor, string value
30+
) {
31+
fromTestLocation(container) and
32+
p.hasDefaultValue() and
33+
container.getAParameter() = p and
34+
p.getDefaultValue() = o and
35+
o.getTarget().toStringWithTypes() = constructor and
36+
o.getAnArgument().getValue() = value and
37+
not compilerGeneratedAttribute(container)
1938
}

0 commit comments

Comments
 (0)