mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #15043 from hvitved/ql/redundant-import
QL4QL: Improvements to `RedundantImport` query
This commit is contained in:
@@ -6,14 +6,12 @@ import experimental.adaptivethreatmodeling.EndpointTypes
|
||||
private import semmle.javascript.security.dataflow.SqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
private import semmle.javascript.security.dataflow.NosqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.TaintedPathCustomizations
|
||||
private import semmle.javascript.heuristics.SyntacticHeuristics as SyntacticHeuristics
|
||||
private import semmle.javascript.filters.ClassifyFiles as ClassifyFiles
|
||||
private import semmle.javascript.security.dataflow.XxeCustomizations
|
||||
private import semmle.javascript.security.dataflow.RemotePropertyInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.TypeConfusionThroughParameterTamperingCustomizations
|
||||
private import semmle.javascript.security.dataflow.ZipSlipCustomizations
|
||||
private import semmle.javascript.security.dataflow.TaintedPathCustomizations
|
||||
private import semmle.javascript.security.dataflow.CleartextLoggingCustomizations
|
||||
private import semmle.javascript.security.dataflow.XpathInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.Xss::Shared as Xss
|
||||
@@ -28,10 +26,8 @@ private import semmle.javascript.security.dataflow.CommandInjectionCustomization
|
||||
private import semmle.javascript.security.dataflow.PrototypePollutionCustomizations
|
||||
private import semmle.javascript.security.dataflow.UnvalidatedDynamicMethodCallCustomizations
|
||||
private import semmle.javascript.security.dataflow.TaintedFormatStringCustomizations
|
||||
private import semmle.javascript.security.dataflow.NosqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.PostMessageStarCustomizations
|
||||
private import semmle.javascript.security.dataflow.RegExpInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.SqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.InsecureRandomnessCustomizations
|
||||
private import semmle.javascript.security.dataflow.XmlBombCustomizations
|
||||
private import semmle.javascript.security.dataflow.InsufficientPasswordHashCustomizations
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
|
||||
import javascript
|
||||
import experimental.adaptivethreatmodeling.AdaptiveThreatModeling
|
||||
import experimental.adaptivethreatmodeling.ATMConfig
|
||||
import experimental.adaptivethreatmodeling.BaseScoring
|
||||
import experimental.adaptivethreatmodeling.EndpointFeatures as EndpointFeatures
|
||||
import experimental.adaptivethreatmodeling.EndpointTypes
|
||||
import semmle.javascript.security.dataflow.NosqlInjectionCustomizations
|
||||
|
||||
/** Gets the positive endpoint type for which you wish to find misclassified examples. */
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
import semmle.javascript.security.dataflow.NosqlInjectionCustomizations
|
||||
import semmle.javascript.security.dataflow.SqlInjectionCustomizations
|
||||
import semmle.javascript.security.dataflow.TaintedPathCustomizations
|
||||
import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
import semmle.javascript.security.dataflow.ShellCommandInjectionFromEnvironmentCustomizations
|
||||
import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionAtm
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
private import javascript
|
||||
private import internal.FlowSteps
|
||||
private import internal.AccessPaths
|
||||
private import internal.CallGraphs
|
||||
private import semmle.javascript.Unit
|
||||
private import semmle.javascript.internal.CachedStages
|
||||
|
||||
|
||||
@@ -27,10 +27,8 @@
|
||||
|
||||
private import javascript
|
||||
import AbstractValues
|
||||
import AbstractProperties
|
||||
private import InferredTypes
|
||||
private import Refinements
|
||||
private import internal.AbstractValuesImpl
|
||||
import internal.BasicExprTypeInference
|
||||
import internal.InterModuleTypeInference
|
||||
import internal.InterProceduralTypeInference
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
import javascript
|
||||
private import AngularJS
|
||||
private import ServiceDefinitions
|
||||
|
||||
/**
|
||||
* Holds if `nd` is an `angular.injector()` value
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.frameworks.HTTP
|
||||
import semmle.javascript.frameworks.ExpressModules
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpressShared
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.TaintedObject
|
||||
import LoopBoundInjectionCustomizations::LoopBoundInjection
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.TaintedObject
|
||||
import semmle.javascript.dependencies.Dependencies
|
||||
import semmle.javascript.dependencies.SemVer
|
||||
|
||||
module PrototypePollution {
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.TaintedObject
|
||||
import semmle.javascript.dependencies.Dependencies
|
||||
import semmle.javascript.dependencies.SemVer
|
||||
import PrototypePollutionCustomizations::PrototypePollution
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import meta.MetaMetrics
|
||||
private import Expressions.ExprHasNoEffect
|
||||
import meta.internal.TaintMetrics
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import javascript
|
||||
import semmle.javascript.dependencies.Dependencies
|
||||
import semmle.javascript.dependencies.SemVer
|
||||
|
||||
class SampleVersionSink extends DataFlow::Node {
|
||||
|
||||
@@ -889,6 +889,9 @@ class ModuleMember extends TModuleMember, AstNode {
|
||||
|
||||
/** Holds if this member is declared as `final`. */
|
||||
predicate isFinal() { this.hasAnnotation("final") }
|
||||
|
||||
/** Holds if this member is declared as `deprecated`. */
|
||||
predicate isDeprecated() { this.hasAnnotation("deprecated") }
|
||||
}
|
||||
|
||||
private newtype TDeclarationKind =
|
||||
@@ -2738,6 +2741,18 @@ module YAML {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the language library file for this QLPack, if any. For example, the
|
||||
* language library file for `codeql/cpp-all` is `cpp.qll`.
|
||||
*/
|
||||
File getLanguageLib() {
|
||||
exists(string name |
|
||||
name = this.getExtractor() and
|
||||
result.getParentContainer() = this.getFile().getParentContainer() and
|
||||
result.getBaseName() = name + ".qll"
|
||||
)
|
||||
}
|
||||
|
||||
Location getLocation() {
|
||||
// hacky, just pick the first node in the file.
|
||||
result =
|
||||
|
||||
@@ -1,68 +1,64 @@
|
||||
import ql
|
||||
private import YAML
|
||||
private import codeql_ql.ast.internal.Module
|
||||
|
||||
Import imports(Import imp) {
|
||||
private FileOrModule getResolvedModule(Import imp) {
|
||||
result = imp.getResolvedModule() and
|
||||
// skip the top-level language files
|
||||
not result.asFile() = any(QLPack p).getLanguageLib()
|
||||
}
|
||||
|
||||
private Import imports(Import imp) {
|
||||
(
|
||||
exists(File file, TopLevel top |
|
||||
imp.getResolvedModule().asFile() = file and
|
||||
getResolvedModule(imp).asFile() = file and
|
||||
top.getLocation().getFile() = file and
|
||||
result = top.getAMember()
|
||||
)
|
||||
or
|
||||
exists(Module mod |
|
||||
imp.getResolvedModule().asModule() = mod and
|
||||
getResolvedModule(imp).asModule() = mod and
|
||||
result = mod.getAMember()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Import getAnImport(AstNode parent) {
|
||||
private Import getAnImport(AstNode parent) {
|
||||
result = parent.(TopLevel).getAMember()
|
||||
or
|
||||
result = parent.(Module).getAMember()
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
predicate importsFromSameFolder(Import a, Import b) {
|
||||
exists(string base |
|
||||
a.getImportString().regexpCapture("(.*)\\.[^\\.]*", 1) = base and
|
||||
b.getImportString().regexpCapture("(.*)\\.[^\\.]*", 1) = base
|
||||
)
|
||||
or
|
||||
not a.getImportString().matches("%.%") and
|
||||
not b.getImportString().matches("%.%")
|
||||
}
|
||||
|
||||
predicate problem(Import imp, Import redundant, string message) {
|
||||
not exists(imp.importedAs()) and
|
||||
not exists(redundant.importedAs()) and
|
||||
not exists(imp.getModuleExpr().getQualifier*().getArgument(_)) and // any type-arguments, and we ignore, they might be different.
|
||||
// skip the top-level language files, they have redundant imports, and that's fine.
|
||||
not exists(imp.getLocation().getFile().getParentContainer().getFile("qlpack.yml")) and
|
||||
not imp.getLocation().getFile() = any(QLPack p).getLanguageLib() and
|
||||
// skip the DataFlowImpl.qll and similar, they have redundant imports in some copies.
|
||||
not imp.getLocation()
|
||||
.getFile()
|
||||
.getBaseName()
|
||||
.regexpMatch([".*Impl\\d?\\.qll", "DataFlowImpl.*\\.qll"]) and
|
||||
// skip two imports that imports different things from the same folder.
|
||||
not importsFromSameFolder(imp, redundant) and
|
||||
// if the redundant is public, and the imp is private, then the redundant might add things that are exported.
|
||||
not (imp.isPrivate() and not redundant.isPrivate()) and
|
||||
// Actually checking if the import is redundant:
|
||||
exists(AstNode parent |
|
||||
imp = getAnImport(parent) and
|
||||
redundant = getAnImport(parent) and
|
||||
redundant.getLocation().getStartLine() > imp.getLocation().getStartLine()
|
||||
redundant = getAnImport(parent)
|
||||
|
|
||||
message = "Redundant import, the module is already imported inside $@." and
|
||||
// only looking for things directly imported one level down. Otherwise things gets complicated (lots of cycles).
|
||||
exists(Import inner | inner = imports(imp) |
|
||||
redundant.getResolvedModule() = inner.getResolvedModule() and
|
||||
getResolvedModule(redundant) = getResolvedModule(inner) and
|
||||
not inner.isPrivate() and // if the inner is private, then it's not propagated out.
|
||||
not inner.isDeprecated() and
|
||||
not exists(inner.importedAs())
|
||||
)
|
||||
or
|
||||
message = "Duplicate import, the module is already imported by $@." and
|
||||
// two different import statements, that import the same thing
|
||||
imp.getResolvedModule() = redundant.getResolvedModule()
|
||||
getResolvedModule(imp) = getResolvedModule(redundant) and
|
||||
redundant.getLocation().getStartLine() > imp.getLocation().getStartLine()
|
||||
)
|
||||
}
|
||||
|
||||
2
ql/ql/test/queries/style/RedundantImport/D.qll
Normal file
2
ql/ql/test/queries/style/RedundantImport/D.qll
Normal file
@@ -0,0 +1,2 @@
|
||||
import folder.A
|
||||
import folder.B
|
||||
2
ql/ql/test/queries/style/RedundantImport/E.qll
Normal file
2
ql/ql/test/queries/style/RedundantImport/E.qll
Normal file
@@ -0,0 +1,2 @@
|
||||
import folder.A
|
||||
import folder.C
|
||||
@@ -0,0 +1 @@
|
||||
| D.qll:1:1:1:15 | Import | Redundant import, the module is already imported inside $@. | D.qll:2:1:2:15 | Import | folder.B |
|
||||
@@ -0,0 +1 @@
|
||||
queries/style/RedundantImport.ql
|
||||
1
ql/ql/test/queries/style/RedundantImport/folder/A.qll
Normal file
1
ql/ql/test/queries/style/RedundantImport/folder/A.qll
Normal file
@@ -0,0 +1 @@
|
||||
predicate p() { any() }
|
||||
1
ql/ql/test/queries/style/RedundantImport/folder/B.qll
Normal file
1
ql/ql/test/queries/style/RedundantImport/folder/B.qll
Normal file
@@ -0,0 +1 @@
|
||||
import A
|
||||
1
ql/ql/test/queries/style/RedundantImport/folder/C.qll
Normal file
1
ql/ql/test/queries/style/RedundantImport/folder/C.qll
Normal file
@@ -0,0 +1 @@
|
||||
deprecated import A
|
||||
Reference in New Issue
Block a user