C#: Address comments in the QL implementation.

This commit is contained in:
Michael Nebel
2025-11-07 15:52:37 +01:00
parent 1657dfb551
commit 9d300e3ad3
3 changed files with 65 additions and 70 deletions

View File

@@ -36,7 +36,7 @@ import semmle.code.csharp.controlflow.ControlFlowGraph
import semmle.code.csharp.dataflow.DataFlow
import semmle.code.csharp.dataflow.TaintTracking
import semmle.code.csharp.dataflow.SSA
private import semmle.code.csharp.Overlay
private import semmle.code.csharp.internal.Overlay
/** Whether the source was extracted without a build command. */
predicate extractionIsStandalone() { exists(SourceFile f | f.extractedStandalone()) }

View File

@@ -10,73 +10,19 @@
overlay[local]
predicate isOverlay() { databaseMetadata("isOverlay", "true") }
overlay[local]
private string getLocationFilePath(@location_default loc) {
exists(@file file | locations_default(loc, file, _, _, _, _) | files(file, result))
}
/**
* An abstract base class for all elements that can be discarded from the base.
*/
overlay[local]
abstract private class DiscardableEntity extends @locatable {
private class DiscardableEntity extends @locatable {
/** Gets the path to the file in which this element occurs. */
abstract string getPath();
/** Holds if this element exists in the base variant. */
predicate existsInBase() { not isOverlay() and exists(this) }
/** Holds if this element exists in the overlay variant. */
predicate existsInOverlay() { isOverlay() and exists(this) }
/** Gets a textual representation of this discardable element. */
string toString() { none() }
}
/**
* A class of C# database entities that use `*` IDs.
* The rest use named TRAP IDs.
*/
overlay[local]
private class StarEntity =
@expr or @stmt or @diagnostic or @extractor_message or @using_directive or @type_mention;
overlay[discard_entity]
private predicate discardStarEntity(@locatable e) {
e instanceof StarEntity and
// Entities with *-ids can exist either in base or overlay, but not both.
exists(DiscardableEntity de | de = e |
overlayChangedFiles(de.getPath()) and
de.existsInBase()
)
}
overlay[discard_entity]
private predicate discardNamedEntity(@locatable e) {
not e instanceof StarEntity and
// Entities with named IDs can exist both in base, overlay, or both.
exists(DiscardableEntity de | de = e |
overlayChangedFiles(de.getPath()) and
not de.existsInOverlay()
)
}
overlay[local]
private string getLocationPath(@location_default loc) {
exists(@file file | locations_default(loc, file, _, _, _, _) | files(file, result))
}
overlay[local]
private predicate discardableLocation(@location_default loc, string path) {
not isOverlay() and
path = getLocationPath(loc)
}
// Discard locations that are in changed files from the base variant.
overlay[discard_entity]
private predicate discardLocation(@location_default loc) {
exists(string path | discardableLocation(loc, path) | overlayChangedFiles(path))
}
overlay[local]
private class PossibleDiscardableEntity extends DiscardableEntity instanceof @locatable {
override string getPath() {
exists(@location_default loc | result = getLocationPath(loc) |
string getFilePath() {
exists(@location_default loc | result = getLocationFilePath(loc) |
expr_location(this, loc) or
stmt_location(this, loc) or
using_directive_location(this, loc) or
@@ -104,4 +50,56 @@ private class PossibleDiscardableEntity extends DiscardableEntity instanceof @lo
extractor_messages(this, _, _, _, _, loc, _)
)
}
/** Holds if this element exists in the base variant. */
predicate existsInBase() { not isOverlay() and exists(this) }
/** Holds if this element exists in the overlay variant. */
predicate existsInOverlay() { isOverlay() and exists(this) }
/** Gets a textual representation of this discardable element. */
string toString() { none() }
}
/**
* A class of C# database entities that use `*` IDs.
* The rest use named TRAP IDs.
*/
overlay[local]
private class StarEntity =
@expr or @stmt or @diagnostic or @extractor_message or @using_directive or @type_mention or
@local_variable;
overlay[discard_entity]
private predicate discardStarEntity(@locatable e) {
e instanceof StarEntity and
// Entities with *-ids can exist either in base or overlay, but not both.
e =
any(DiscardableEntity de |
overlayChangedFiles(de.getFilePath()) and
de.existsInBase()
)
}
overlay[discard_entity]
private predicate discardNamedEntity(@locatable e) {
not e instanceof StarEntity and
// Entities with named IDs can exist both in base, overlay, or both.
e =
any(DiscardableEntity de |
overlayChangedFiles(de.getFilePath()) and
not de.existsInOverlay()
)
}
overlay[local]
private predicate discardableLocation(@location_default loc, string path) {
not isOverlay() and
path = getLocationFilePath(loc)
}
// Discard locations that are in changed files from the base variant.
overlay[discard_entity]
private predicate discardLocation(@location_default loc) {
exists(string path | discardableLocation(loc, path) | overlayChangedFiles(path))
}

View File

@@ -5,25 +5,22 @@ import csharp
query predicate elementsWithMultipleSourceLocations(Element e, SourceLocation loc) {
e.fromSource() and
not e instanceof Namespace and
count(SourceLocation l0 | l0 = e.getALocation()) > 1 and
strictcount(SourceLocation l0 | l0 = e.getALocation()) > 1 and
loc = e.getALocation()
}
query predicate typeMentionsWithMultipleSourceLocations(TypeMention tm, SourceLocation loc) {
tm.getLocation().getFile().fromSource() and
count(SourceLocation l0 | l0 = tm.getLocation()) > 1 and
strictcount(SourceLocation l0 | l0 = tm.getLocation()) > 1 and
loc = tm.getLocation()
}
query predicate commentLinesWithMultipleSourceLocations(CommentLine cl, SourceLocation loc) {
cl.getLocation().getFile().fromSource() and
count(SourceLocation l0 | l0 = cl.getLocation()) > 1 and
strictcount(SourceLocation l0 | l0 = cl.getLocation()) > 1 and
loc = cl.getLocation()
}
query predicate commentBlocksWithMultipleSourceLocations(CommentBlock cb, SourceLocation loc) {
cb.getLocation().getFile().fromSource() and
count(SourceLocation l0 | l0 = cb.getLocation()) > 1 and
strictcount(SourceLocation l0 | l0 = cb.getLocation()) > 1 and
loc = cb.getLocation()
}