Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
23e42c8
JS: Overlay annotations for AST layer
asgerf Aug 29, 2025
2b338fc
JS: Fix getRawEnclosingStmt call
asgerf Oct 3, 2025
b1418e1
JS: Add overlay[local?] to new summaries after rebasing
asgerf Oct 10, 2025
c09563f
JS: Make more general-purpose data flow things local
asgerf Oct 10, 2025
8892097
JS: Overlay annotations for some failing tests
tausbn Oct 10, 2025
66febb2
JS: Add some overlay[caller] and a pragma[nomagic] annotations
asgerf Oct 15, 2025
e72232f
JS: Add more overlay[caller?] annotations
asgerf Oct 15, 2025
ac3913e
JS: Fix bad join in DuplicateProperty.ql
asgerf Oct 16, 2025
5dd87e3
JS: Add overlay[local] to restore magic in unwrap() predicate
asgerf Oct 16, 2025
269489e
JS: Avoid bad join in shared predicate induced by 'forex'.
asgerf Oct 16, 2025
4645f32
JS: Avoid more bad joins due to locality
asgerf Oct 20, 2025
0594f84
JS: Improve join orders related to getABooleanValue()
asgerf Oct 22, 2025
6498cd1
JS: Remove obsolete overlay[global] annotations
asgerf Oct 31, 2025
46b1387
JS: Make isAssignedInUniqueFile global, as it should be
asgerf Nov 3, 2025
16e7dc1
Sync ApiGraphModelsExtensions.qll
asgerf Nov 3, 2025
ecfa946
Sync ApiGraphModels.qll
asgerf Nov 3, 2025
578355a
JS: Fix bad join in CallGraphs.qll
asgerf Nov 11, 2025
c7341f2
JS: Fix bad join in BarrierGuards.qll
asgerf Nov 11, 2025
a405b7b
JS: Add discard predicates for locations
asgerf Nov 17, 2025
4b57b44
JS: Factor out some code
asgerf Nov 17, 2025
a0965f3
JS: Also discard JSON, YAML, and XML
asgerf Nov 18, 2025
8fef604
JS: Remove out-commented code
asgerf Nov 19, 2025
efa438a
JS: Move identityFunctionStep back into CachedSteps module
asgerf Nov 19, 2025
8ed22e1
Factor XML discard predicates into OverlayXml.qll
asgerf Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions config/identical-files.json
Original file line number Diff line number Diff line change
Expand Up @@ -276,5 +276,12 @@
"Python model summaries test extension": [
"python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml",
"python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml"
],
"XML discard predicates": [
"javascript/ql/lib/semmle/javascript/internal/OverlayXml.qll",
"java/ql/lib/semmle/code/java/internal/OverlayXml.qll",
"go/ql/lib/semmle/go/internal/OverlayXml.qll",
"python/ql/lib/semmle/python/internal/OverlayXml.qll",
"csharp/ql/lib/semmle/code/csharp/internal/OverlayXml.qll"
]
}
32 changes: 2 additions & 30 deletions csharp/ql/lib/semmle/code/csharp/internal/Overlay.qll
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
* Defines entity discard predicates for C# overlay analysis.
*/

private import OverlayXml

/**
* Holds always for the overlay variant and never for the base variant.
* This local predicate is used to define local predicates that behave
Expand Down Expand Up @@ -110,36 +112,6 @@ private predicate discardLocation(@location_default loc) {
exists(string path | discardableLocation(loc, path) | overlayChangedFiles(path))
}

/**
* A class of Xml locatables that can be discarded from the base.
*/
overlay[local]
private class DiscardableXmlEntity extends DiscardableEntityBase instanceof @xmllocatable {
/** Gets the path to the file in which this element occurs. */
override string getFilePath() {
exists(@location_default loc | result = getLocationFilePath(loc) | xmllocations(this, loc))
}
}

overlay[local]
private predicate overlayXmlExtracted(string file) {
exists(DiscardableXmlEntity dxe |
dxe.existsInOverlay() and
file = dxe.getFilePath() and
not files(dxe, _) and
not xmlNs(dxe, _, _, _)
)
}

overlay[discard_entity]
private predicate discardXmlEntity(@xmllocatable xml) {
overlayChangedFiles(xml.(DiscardableXmlEntity).getFilePath())
or
// The XML extractor is not incremental and may extract more
// XML files than those included in overlayChangedFiles.
overlayXmlExtracted(xml.(DiscardableXmlEntity).getFilePath())
}

overlay[local]
private class DiscardableAspEntity extends DiscardableEntityBase instanceof @asp_element {
/** Gets the path to the file in which this element occurs. */
Expand Down
45 changes: 45 additions & 0 deletions csharp/ql/lib/semmle/code/csharp/internal/OverlayXml.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
overlay[local]
module;

/**
* A local predicate that always holds for the overlay variant and never holds for the base variant.
* This is used to define local predicates that behave differently for the base and overlay variant.
*/
private predicate isOverlay() { databaseMetadata("isOverlay", "true") }

private @file getXmlFile(@xmllocatable locatable) {
exists(@location_default location | xmllocations(locatable, location) |
locations_default(location, result, _, _, _, _)
)
}

private @file getXmlFileInBase(@xmllocatable locatable) {
not isOverlay() and
result = getXmlFile(locatable)
}

/**
* Holds if the given `file` was extracted as part of the overlay and was extracted by the HTML/XML
* extractor.
*/
private predicate overlayXmlExtracted(@file file) {
isOverlay() and
exists(@xmllocatable locatable |
not files(locatable, _) and not xmlNs(locatable, _, _, _) and file = getXmlFile(locatable)
)
}

/**
* Holds if the given XML `locatable` should be discarded, because it is part of the overlay base
* and is in a file that was also extracted as part of the overlay database.
*/
overlay[discard_entity]
private predicate discardXmlLocatable(@xmllocatable locatable) {
exists(@file file | file = getXmlFileInBase(locatable) |
exists(string path | files(file, path) | overlayChangedFiles(path))
or
// The HTML/XML extractor is currently not incremental and may extract more files than those
// included in overlayChangedFiles.
overlayXmlExtracted(file)
)
}
39 changes: 2 additions & 37 deletions go/ql/lib/semmle/go/Overlay.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
overlay[local]
module;

private import internal.OverlayXml

/**
* A local predicate that always holds for the overlay variant and never holds for the base variant.
* This is used to define local predicates that behave differently for the base and overlay variant.
Expand Down Expand Up @@ -52,40 +54,3 @@ private predicate discardLocatable(@locatable locatable) {
discardableLocatable(file, locatable) and discardableFile(path)
)
}

private @file getXmlFile(@xmllocatable locatable) {
exists(@location_default location | xmllocations(locatable, location) |
locations_default(location, result, _, _, _, _)
)
}

private @file getXmlFileInBase(@xmllocatable locatable) {
not isOverlay() and
result = getXmlFile(locatable)
}

/**
* Holds if the given `file` was extracted as part of the overlay and was extracted by the HTML/XML
* extractor.
*/
private predicate overlayXmlExtracted(@file file) {
isOverlay() and
exists(@xmllocatable locatable |
not files(locatable, _) and not xmlNs(locatable, _, _, _) and file = getXmlFile(locatable)
)
}

/**
* Holds if the given XML `locatable` should be discarded, because it is part of the overlay base
* and is in a file that was also extracted as part of the overlay database.
*/
overlay[discard_entity]
private predicate discardXmlLocatable(@xmllocatable locatable) {
exists(@file file | file = getXmlFileInBase(locatable) |
exists(string path | files(file, path) | overlayChangedFiles(path))
or
// The HTML/XML extractor is currently not incremental and may extract more files than those
// included in overlayChangedFiles.
overlayXmlExtracted(file)
)
}
45 changes: 45 additions & 0 deletions go/ql/lib/semmle/go/internal/OverlayXml.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
overlay[local]
module;

/**
* A local predicate that always holds for the overlay variant and never holds for the base variant.
* This is used to define local predicates that behave differently for the base and overlay variant.
*/
private predicate isOverlay() { databaseMetadata("isOverlay", "true") }

private @file getXmlFile(@xmllocatable locatable) {
exists(@location_default location | xmllocations(locatable, location) |
locations_default(location, result, _, _, _, _)
)
}

private @file getXmlFileInBase(@xmllocatable locatable) {
not isOverlay() and
result = getXmlFile(locatable)
}

/**
* Holds if the given `file` was extracted as part of the overlay and was extracted by the HTML/XML
* extractor.
*/
private predicate overlayXmlExtracted(@file file) {
isOverlay() and
exists(@xmllocatable locatable |
not files(locatable, _) and not xmlNs(locatable, _, _, _) and file = getXmlFile(locatable)
)
}

/**
* Holds if the given XML `locatable` should be discarded, because it is part of the overlay base
* and is in a file that was also extracted as part of the overlay database.
*/
overlay[discard_entity]
private predicate discardXmlLocatable(@xmllocatable locatable) {
exists(@file file | file = getXmlFileInBase(locatable) |
exists(string path | files(file, path) | overlayChangedFiles(path))
or
// The HTML/XML extractor is currently not incremental and may extract more files than those
// included in overlayChangedFiles.
overlayXmlExtracted(file)
)
}
31 changes: 2 additions & 29 deletions java/ql/lib/semmle/code/java/Overlay.qll
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ overlay[local?]
module;

import java
private import internal.OverlayXml

/**
* A local predicate that always holds for the overlay variant and
Expand All @@ -18,7 +19,7 @@ predicate isOverlay() { databaseMetadata("isOverlay", "true") }
overlay[local]
string getRawFile(@locatable el) {
exists(@location loc, @file file |
(hasLocation(el, loc) or xmllocations(el, loc)) and
hasLocation(el, loc) and
locations_default(loc, file, _, _, _, _) and
files(file, result)
)
Expand Down Expand Up @@ -102,31 +103,3 @@ private predicate discardBaseConfigLocatable(@configLocatable el) {
// property files than those included in overlayChangedFiles.
overlayConfigExtracted(baseConfigLocatable(el))
}

/**
* An `@xmllocatable` that should be discarded in the base variant if its file is
* extracted in the overlay variant.
*/
overlay[local]
abstract class DiscardableXmlLocatable extends @xmllocatable {
/** Gets the raw file for an xmllocatable in base. */
string getRawFileInBase() { not isOverlay() and result = getRawFile(this) }

/** Gets a textual representation of this discardable xmllocatable. */
string toString() { none() }
}

overlay[local]
private predicate overlayXmlExtracted(string file) {
isOverlay() and
exists(@xmllocatable el | not files(el, _) and not xmlNs(el, _, _, _) and file = getRawFile(el))
}

overlay[discard_entity]
private predicate discardXmlLocatable(@xmllocatable el) {
overlayChangedFiles(el.(DiscardableXmlLocatable).getRawFileInBase())
or
// The XML extractor is currently not incremental and may extract more
// XML files than those included in overlayChangedFiles.
overlayXmlExtracted(el.(DiscardableXmlLocatable).getRawFileInBase())
}
45 changes: 45 additions & 0 deletions java/ql/lib/semmle/code/java/internal/OverlayXml.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
overlay[local]
module;

/**
* A local predicate that always holds for the overlay variant and never holds for the base variant.
* This is used to define local predicates that behave differently for the base and overlay variant.
*/
private predicate isOverlay() { databaseMetadata("isOverlay", "true") }

private @file getXmlFile(@xmllocatable locatable) {
exists(@location_default location | xmllocations(locatable, location) |
locations_default(location, result, _, _, _, _)
)
}

private @file getXmlFileInBase(@xmllocatable locatable) {
not isOverlay() and
result = getXmlFile(locatable)
}

/**
* Holds if the given `file` was extracted as part of the overlay and was extracted by the HTML/XML
* extractor.
*/
private predicate overlayXmlExtracted(@file file) {
isOverlay() and
exists(@xmllocatable locatable |
not files(locatable, _) and not xmlNs(locatable, _, _, _) and file = getXmlFile(locatable)
)
}

/**
* Holds if the given XML `locatable` should be discarded, because it is part of the overlay base
* and is in a file that was also extracted as part of the overlay database.
*/
overlay[discard_entity]
private predicate discardXmlLocatable(@xmllocatable locatable) {
exists(@file file | file = getXmlFileInBase(locatable) |
exists(string path | files(file, path) | overlayChangedFiles(path))
or
// The HTML/XML extractor is currently not incremental and may extract more files than those
// included in overlayChangedFiles.
overlayXmlExtracted(file)
)
}
11 changes: 0 additions & 11 deletions java/ql/lib/semmle/code/xml/XML.qll
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ module;

import semmle.files.FileSystem
private import codeql.xml.Xml
private import semmle.code.java.Overlay

private module Input implements InputSig<File, Location> {
class XmlLocatableBase = @xmllocatable or @xmlnamespaceable;
Expand Down Expand Up @@ -70,13 +69,3 @@ private module Input implements InputSig<File, Location> {
}

import Make<File, Location, Input>

private class DiscardableXmlAttribute extends DiscardableXmlLocatable, @xmlattribute { }

private class DiscardableXmlElement extends DiscardableXmlLocatable, @xmlelement { }

private class DiscardableXmlComment extends DiscardableXmlLocatable, @xmlcomment { }

private class DiscardableXmlCharacters extends DiscardableXmlLocatable, @xmlcharacters { }

private class DiscardableXmlDtd extends DiscardableXmlLocatable, @xmldtd { }
6 changes: 6 additions & 0 deletions javascript/ql/lib/Expressions/ExprHasNoEffect.qll
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/**
* Provides classes and predicates for the 'js/useless-expression' query.
*/
overlay[local]
module;

import javascript
import DOMProperties
Expand Down Expand Up @@ -60,6 +62,7 @@ predicate isDeclaration(Expr e) {
/**
* Holds if there exists a getter for a property called `name` anywhere in the program.
*/
overlay[global]
predicate isGetterProperty(string name) {
// there is a call of the form `Object.defineProperty(..., name, descriptor)` ...
exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() |
Expand All @@ -85,6 +88,7 @@ predicate isGetterProperty(string name) {
/**
* A property access that may invoke a getter.
*/
overlay[global]
class GetterPropertyAccess extends PropAccess {
override predicate isImpure() { isGetterProperty(this.getPropertyName()) }
}
Expand Down Expand Up @@ -123,6 +127,7 @@ predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) {
* even if they do, the call itself is useless and should be flagged by this
* query.
*/
overlay[global]
predicate noSideEffects(Expr e) {
e.isPure()
or
Expand All @@ -148,6 +153,7 @@ predicate isCompoundExpression(Expr e) {
/**
* Holds if the expression `e` should be reported as having no effect.
*/
overlay[global]
predicate hasNoEffect(Expr e) {
noSideEffects(e) and
inVoidContext(e) and
Expand Down
2 changes: 2 additions & 0 deletions javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/**
* Provides a predicate for identifying unused index variables in loops.
*/
overlay[local]
module;

import javascript

Expand Down
Loading
Loading