Skip to content

Commit 25cc89d

Browse files
Max SchaeferGitHub Enterprise
Max Schaefer
authored and
GitHub Enterprise
committed
Merge pull request github#27 from pavel/imp/csharp
Add C# code
2 parents 57d814f + 9ac797a commit 25cc89d

File tree

3,056 files changed

+167428
-0
lines changed

Some content is hidden

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

3,056 files changed

+167428
-0
lines changed

csharp/ql/src/.project

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>semmlecode-csharp-queries</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.eclipse.pde.ManifestBuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
<buildCommand>
14+
<name>org.eclipse.pde.SchemaBuilder</name>
15+
<arguments>
16+
</arguments>
17+
</buildCommand>
18+
</buildSpec>
19+
<natures>
20+
<nature>org.eclipse.pde.PluginNature</nature>
21+
<nature>com.semmle.plugin.qdt.core.qlnature</nature>
22+
</natures>
23+
</projectDescription>

csharp/ql/src/.qlpath

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<ns:qlpath xmlns:ns="https://semmle.com/schemas/qlpath">
3+
<librarypath></librarypath>
4+
<dbscheme kind="WORKSPACE">semmlecode-csharp-queries/semmlecode.csharp.dbscheme</dbscheme>
5+
<defaultImports><defaultImport>csharp</defaultImport></defaultImports>
6+
</ns:qlpath>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"ql.projects" : {
3+
"." : {
4+
"dbScheme" : "semmlecode.csharp.dbscheme",
5+
"libraryPath" : []
6+
}
7+
}
8+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Explicitly forcing garbage collection is not efficient and is almost never necessary outside of
7+
benchmarking scenarios.</p>
8+
9+
</overview>
10+
<recommendation>
11+
<p>Remove the explicit call to <code>GC.Collect()</code> and run a memory profiler to optimize your
12+
application's memory usage. If your application uses unmanaged resources and calls <code>
13+
GC.Collect()</code> to force finalizers to run, it is better to implement the <code>IDisposable
14+
</code> pattern and use <code>try</code>/<code>finally</code> clauses to make sure that unmanaged
15+
resources are disposed of even if an exception interrupts your application.</p>
16+
17+
</recommendation>
18+
<example>
19+
<sample src="CallToGCCollectBad.cs" />
20+
21+
</example>
22+
<references>
23+
24+
<li>MSDN: <a href="http://msdn.microsoft.com/en-us/library/system.idisposable.aspx">The IDisposable interface</a>.</li>
25+
<li>Microsoft: <a href="https://docs.microsoft.com/en-us/visualstudio/profiling/memory-usage">Profile Memory Usage in Visual Studio</a>.</li>
26+
27+
</references>
28+
</qhelp>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @name Call to GC.Collect()
3+
* @description Explicit requests for garbage collection often indicate performance problems and memory leaks.
4+
* @kind problem
5+
* @problem.severity warning
6+
* @precision very-high
7+
* @id cs/call-to-gc
8+
* @tags efficiency
9+
* maintainability
10+
*/
11+
import csharp
12+
13+
from MethodCall c, Method gcCollect
14+
where
15+
c.getTarget() = gcCollect
16+
and gcCollect.hasName("Collect")
17+
and gcCollect.hasNoParameters()
18+
and gcCollect.getDeclaringType().hasQualifiedName("System.GC")
19+
select c, "Call to 'GC.Collect()'."
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System;
2+
3+
class Bad
4+
{
5+
void M()
6+
{
7+
GC.Collect();
8+
}
9+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Methods with the <code>[Obsolete]</code> attribute are obsolete and should not be used.
7+
Obsolete methods are no longer supported and maintained, may not work correctly, and may be removed in the future.</p>
8+
9+
</overview>
10+
<recommendation>
11+
<p>Replace the method call with a call to a different method. The <code>[Obsolete]</code>
12+
attribute should suggest a replacement method to call. If the <code>[Obsolete]</code> attribute
13+
does not suggest a replacement, then read the class documentation and list of methods to find
14+
a suitable replacement.</p>
15+
16+
</recommendation>
17+
<example>
18+
<p>The following example shows some code which calls an obsolete method in a <code>Logger</code> class.
19+
The <code>Log</code> method has the attribute
20+
<code>[Obsolete("Use Log(LogLevel level, string s) instead")]</code>
21+
showing that it is obsolete.</p>
22+
23+
<sample src="CallToObsoleteMethodBad.cs" />
24+
25+
<p>The code is fixed by calling a different method in the <code>Logger</code> class as suggested
26+
by the attribute.</p>
27+
28+
<sample src="CallToObsoleteMethodGood.cs" />
29+
30+
</example>
31+
<references>
32+
33+
<li>MSDN: <a href="https://msdn.microsoft.com/en-us/library/system.obsoleteattribute(v=vs.110).aspx">ObsoleteAttribute Class</a>.</li>
34+
35+
36+
</references>
37+
</qhelp>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @name Call to obsolete method
3+
* @description Calls to methods marked as [Obsolete] should be replaced because the method is
4+
* no longer maintained and may be removed in the future.
5+
* @kind problem
6+
* @problem.severity warning
7+
* @precision very-high
8+
* @id cs/call-to-obsolete-method
9+
* @tags changeability
10+
* maintainability
11+
* external/cwe/cwe-477
12+
*/
13+
14+
import csharp
15+
16+
class ObsoleteAttribute extends Attribute {
17+
ObsoleteAttribute() {
18+
this.getType().hasQualifiedName("System", "ObsoleteAttribute")
19+
}
20+
}
21+
22+
from MethodCall c, Method m
23+
where m = c.getTarget()
24+
and m.getAnAttribute() instanceof ObsoleteAttribute
25+
and not c.getEnclosingCallable().(Attributable).getAnAttribute() instanceof ObsoleteAttribute
26+
select c, "Call to obsolete method $@.", m, m.getName()
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
3+
class Bad
4+
{
5+
void M()
6+
{
7+
Logger.Log("Hello, World!");
8+
}
9+
10+
static class Logger
11+
{
12+
[Obsolete("Use Log(LogLevel level, string s) instead")]
13+
public static void Log(string s)
14+
{
15+
// ...
16+
}
17+
18+
public static void Log(LogLevel level, string s)
19+
{
20+
// ...
21+
}
22+
}
23+
24+
enum LogLevel
25+
{
26+
Info,
27+
Warning,
28+
Error
29+
}
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
3+
class Good
4+
{
5+
void M()
6+
{
7+
Logger.Log(LogLevel.Info, "Hello, World!");
8+
}
9+
10+
static class Logger
11+
{
12+
[Obsolete("Use Log(LogLevel level, string s) instead")]
13+
public static void Log(string s)
14+
{
15+
// ...
16+
}
17+
18+
public static void Log(LogLevel level, string s)
19+
{
20+
// ...
21+
}
22+
}
23+
24+
enum LogLevel
25+
{
26+
Info,
27+
Warning,
28+
Error
29+
}
30+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>When the class of the object on which <code>Equals(object)</code> is called does not define its own
7+
<code>Equals(object)</code> method, an <code>Equals(object)</code> method defined in one of its base
8+
classes will be called instead. In the worst case, the <code>Equals(object)</code> method of
9+
<code>System.Object</code> will be called, resulting in a reference equality check. This is probably
10+
not what was intended.</p>
11+
12+
<p>Classes that implement the <code>==</code> operator should also override the <code>Equals(object)</code>
13+
method, because otherwise the two forms of equality will behave differently, leading to unexpected behavior.</p>
14+
</overview>
15+
<recommendation>
16+
<p>Implement an <code>Equals(object)</code> method for the highlighted class. Examine subclasses of the
17+
class highlighted to determine if they should implement their own equals method too.</p>
18+
19+
</recommendation>
20+
<example>
21+
<p>The output of this example states that "car1 does equal car2" despite the fact that one is a
22+
leaded version and one is an unleaded version. This is because the <code>GasolineCar</code> class
23+
is inheriting <code>Equals(object)</code> from <code>Car</code> and that method states that two
24+
<code>Car</code>s are equal if their make and model are the same.</p>
25+
<sample src="ClassDoesNotImplementEqualsBad.cs" />
26+
27+
<p>
28+
In the revised example, <code>GasolineCar</code> overrides <code>Equals(object)</code>, and the output
29+
is "car1 does not equal car2", as expected.
30+
</p>
31+
<sample src="ClassDoesNotImplementEqualsGood.cs" />
32+
</example>
33+
34+
<references>
35+
<li>Microsoft: <a href="https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators">Equality Operators</a>,
36+
<a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/equality-comparisons">Equality Comparisons (C# Programming Guide)</a>.</li>
37+
</references>
38+
39+
</qhelp>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* @name Class does not implement Equals(object)
3+
* @description The class does not implement the 'Equals(object)' method, which can cause
4+
* unexpected behavior. The default 'Equals(object)' method performs reference
5+
* comparison, which may not be what was intended.
6+
* @kind problem
7+
* @problem.severity error
8+
* @precision medium
9+
* @id cs/class-missing-equals
10+
* @tags reliability
11+
* maintainability
12+
*/
13+
14+
import csharp
15+
import semmle.code.csharp.frameworks.System
16+
17+
from Class c, Element item, string message, string itemText
18+
where
19+
c.isSourceDeclaration()
20+
and not implementsEquals(c)
21+
and not c.isAbstract()
22+
and
23+
(
24+
exists(MethodCall callToEquals |
25+
callToEquals.getTarget() instanceof EqualsMethod
26+
and callToEquals.getQualifier().getType() = c
27+
and message = "but it is called $@"
28+
and item = callToEquals
29+
and itemText = "here" )
30+
or
31+
( item = c.getAnOperator().(EQOperator)
32+
and message = "but it implements $@"
33+
and itemText = "operator ==" )
34+
or
35+
exists(IEquatableEqualsMethod eq | item = eq
36+
and eq = c.getAMethod()
37+
and message = "but it implements $@"
38+
and itemText = "IEquatable<" + eq.getParameter(0).getType() + ">.Equals"
39+
)
40+
)
41+
42+
select c, "Class '" + c.getName() + "' does not implement Equals(object), " + message + ".",
43+
item, itemText
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
3+
class Bad
4+
{
5+
class Car
6+
{
7+
protected string make;
8+
protected string model;
9+
10+
public Car(string make, string model)
11+
{
12+
this.make = make;
13+
this.model = model;
14+
}
15+
16+
public override bool Equals(object obj)
17+
{
18+
if (obj is Car c && c.GetType() == typeof(Car))
19+
return make == c.make && model == c.model;
20+
return false;
21+
}
22+
}
23+
24+
class GasolineCar : Car
25+
{
26+
protected bool unleaded;
27+
28+
public GasolineCar(string make, string model, bool unleaded) : base(make, model)
29+
{
30+
this.unleaded = unleaded;
31+
}
32+
}
33+
34+
public static void Main(string[] args)
35+
{
36+
var car1 = new GasolineCar("Ford", "Focus", true);
37+
var car2 = new GasolineCar("Ford", "Focus", false);
38+
Console.WriteLine("car1 " + (car1.Equals(car2) ? "does" : "does not") + " equal car2.");
39+
}
40+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
3+
class Good
4+
{
5+
class Car
6+
{
7+
protected string make;
8+
protected string model;
9+
10+
public Car(string make, string model)
11+
{
12+
this.make = make;
13+
this.model = model;
14+
}
15+
16+
public override bool Equals(object obj)
17+
{
18+
if (obj is Car c && c.GetType() == typeof(Car))
19+
return make == c.make && model == c.model;
20+
return false;
21+
}
22+
}
23+
24+
class GasolineCar : Car
25+
{
26+
protected bool unleaded;
27+
28+
public GasolineCar(string make, string model, bool unleaded) : base(make, model)
29+
{
30+
this.unleaded = unleaded;
31+
}
32+
33+
public override bool Equals(object obj)
34+
{
35+
if (obj is GasolineCar gc && gc.GetType() == typeof(GasolineCar))
36+
return make == gc.make && model == gc.model && unleaded == gc.unleaded;
37+
return false;
38+
}
39+
}
40+
41+
public static void Main(string[] args)
42+
{
43+
var car1 = new GasolineCar("Ford", "Focus", true);
44+
var car2 = new GasolineCar("Ford", "Focus", false);
45+
Console.WriteLine("car1 " + (car1.Equals(car2) ? "does" : "does not") + " equal car2.");
46+
}
47+
}

0 commit comments

Comments
 (0)