зеркало из https://github.com/github/codeql.git
C#: Avoid using `ExceptionClass` in deliberate Cartesian products
Using the class `ExceptionClass` in combination with a deliberate Cartesian product can lead to bad join orders, for example ``` EVALUATE NONRECURSIVE RELATION: Completion::TriedControlFlowElement::getAThrownException_dispred#ff(int this, int result) :- {1} r1 = JOIN Expr::Expr::getType_dispred#ff_10#join_rhs WITH @integral_type#f ON Expr::Expr::getType_dispred#ff_10#join_rhs.<0>=@integral_type#f.<0> OUTPUT FIELDS {Expr::Expr::getType_dispred#ff_10#join_rhs.<1>} {1} r2 = JOIN r1 WITH @un_op#f ON r1.<0>=@un_op#f.<0> OUTPUT FIELDS {r1.<0>} {1} r3 = JOIN r2 WITH Stmt::TryStmt::getATriedElement#ff_1#join_rhs ON r2.<0>=Stmt::TryStmt::getATriedElement#ff_1#join_rhs.<0> OUTPUT FIELDS {r2.<0>} {2} r4 = JOIN r3 WITH Stmt::ExceptionClass#f CARTESIAN PRODUCT OUTPUT FIELDS {Stmt::ExceptionClass#f.<0>,r3.<0>} {2} r5 = JOIN r4 WITH System::SystemOverflowExceptionClass#class#f ON r4.<0>=System::SystemOverflowExceptionClass#class#f.<0> OUTPUT FIELDS {r4.<1>,r4.<0>} ``` where the CP is made with `ExceptionClass` rather than `SystemOverflowExceptionClass` directly.
This commit is contained in:
Родитель
87c5872bc5
Коммит
e663abd5da
|
@ -23,7 +23,7 @@ import semmle.code.csharp.frameworks.System
|
||||||
* Gets an exception type that may be thrown during the execution of method `m`.
|
* Gets an exception type that may be thrown during the execution of method `m`.
|
||||||
* Assumes any exception may be thrown by library types.
|
* Assumes any exception may be thrown by library types.
|
||||||
*/
|
*/
|
||||||
ExceptionClass getAThrownException(Method m) {
|
Class getAThrownException(Method m) {
|
||||||
m.fromLibrary() and
|
m.fromLibrary() and
|
||||||
result = any(SystemExceptionClass sc)
|
result = any(SystemExceptionClass sc)
|
||||||
or
|
or
|
||||||
|
|
|
@ -15,7 +15,7 @@ abstract class AssertMethod extends Method {
|
||||||
final Parameter getAssertedParameter() { result = this.getParameter(this.getAssertionIndex()) }
|
final Parameter getAssertedParameter() { result = this.getParameter(this.getAssertionIndex()) }
|
||||||
|
|
||||||
/** Gets the exception being thrown if the assertion fails, if any. */
|
/** Gets the exception being thrown if the assertion fails, if any. */
|
||||||
abstract ExceptionClass getExceptionClass();
|
abstract Class getExceptionClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A positive assertion method. */
|
/** A positive assertion method. */
|
||||||
|
@ -122,7 +122,7 @@ class SystemDiagnosticsDebugAssertTrueMethod extends AssertTrueMethod {
|
||||||
|
|
||||||
override int getAssertionIndex() { result = 0 }
|
override int getAssertionIndex() { result = 0 }
|
||||||
|
|
||||||
override ExceptionClass getExceptionClass() {
|
override Class getExceptionClass() {
|
||||||
// A failing assertion generates a message box, see
|
// A failing assertion generates a message box, see
|
||||||
// https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debug.assert
|
// https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debug.assert
|
||||||
none()
|
none()
|
||||||
|
@ -182,7 +182,7 @@ class ForwarderAssertMethod extends AssertMethod {
|
||||||
|
|
||||||
override int getAssertionIndex() { result = p.getPosition() }
|
override int getAssertionIndex() { result = p.getPosition() }
|
||||||
|
|
||||||
override ExceptionClass getExceptionClass() {
|
override Class getExceptionClass() {
|
||||||
result = this.getUnderlyingAssertMethod().getExceptionClass()
|
result = this.getUnderlyingAssertMethod().getExceptionClass()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,13 @@ private predicate isMatchingConstant(Expr e, boolean value) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class Overflowable extends UnaryOperation {
|
||||||
|
Overflowable() {
|
||||||
|
not this instanceof UnaryBitwiseOperation and
|
||||||
|
this.getType() instanceof IntegralType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** A control flow element that is inside a `try` block. */
|
/** A control flow element that is inside a `try` block. */
|
||||||
private class TriedControlFlowElement extends ControlFlowElement {
|
private class TriedControlFlowElement extends ControlFlowElement {
|
||||||
TriedControlFlowElement() { this = any(TryStmt try).getATriedElement() }
|
TriedControlFlowElement() { this = any(TryStmt try).getATriedElement() }
|
||||||
|
@ -185,20 +192,15 @@ private class TriedControlFlowElement extends ControlFlowElement {
|
||||||
/**
|
/**
|
||||||
* Gets an exception class that is potentially thrown by this element, if any.
|
* Gets an exception class that is potentially thrown by this element, if any.
|
||||||
*/
|
*/
|
||||||
ExceptionClass getAThrownException() {
|
Class getAThrownException() {
|
||||||
this = any(UnaryOperation uo |
|
this instanceof Overflowable and
|
||||||
not uo instanceof UnaryBitwiseOperation and
|
result instanceof SystemOverflowExceptionClass
|
||||||
uo.getType() instanceof IntegralType and
|
|
||||||
result instanceof SystemOverflowExceptionClass
|
|
||||||
)
|
|
||||||
or
|
or
|
||||||
this = any(CastExpr ce |
|
this.(CastExpr).getType() instanceof IntegralType and
|
||||||
ce.getType() instanceof IntegralType and
|
result instanceof SystemOverflowExceptionClass
|
||||||
result instanceof SystemOverflowExceptionClass
|
or
|
||||||
or
|
invalidCastCandidate(this) and
|
||||||
invalidCastCandidate(ce) and
|
result instanceof SystemInvalidCastExceptionClass
|
||||||
result instanceof SystemInvalidCastExceptionClass
|
|
||||||
)
|
|
||||||
or
|
or
|
||||||
this instanceof Call and
|
this instanceof Call and
|
||||||
result instanceof SystemExceptionClass
|
result instanceof SystemExceptionClass
|
||||||
|
|
|
@ -558,7 +558,7 @@ class ThrowElement extends ControlFlowElement, DotNet::Throw, @throw_element {
|
||||||
override Expr getExpr() { result = this.getChild(0) }
|
override Expr getExpr() { result = this.getChild(0) }
|
||||||
|
|
||||||
/** Gets the type of exception being thrown. */
|
/** Gets the type of exception being thrown. */
|
||||||
ExceptionClass getThrownExceptionType() {
|
Class getThrownExceptionType() {
|
||||||
result = getExpr().getType()
|
result = getExpr().getType()
|
||||||
or
|
or
|
||||||
// Corner case: `throw null`
|
// Corner case: `throw null`
|
||||||
|
|
|
@ -89,7 +89,7 @@ class VSTestAssertClass extends Class {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The `Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException` class. */
|
/** The `Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException` class. */
|
||||||
class AssertFailedExceptionClass extends ExceptionClass {
|
class AssertFailedExceptionClass extends Class {
|
||||||
AssertFailedExceptionClass() {
|
AssertFailedExceptionClass() {
|
||||||
this.getNamespace() instanceof VSTestNamespace and
|
this.getNamespace() instanceof VSTestNamespace and
|
||||||
this.hasName("AssertFailedException")
|
this.hasName("AssertFailedException")
|
||||||
|
|
Загрузка…
Ссылка в новой задаче