mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge remote-tracking branch 'upstream/master' into set-map-list-copy-of
This commit is contained in:
@@ -15,16 +15,16 @@ class Location extends @location {
|
||||
/** Gets the file corresponding to this location, if any. */
|
||||
File getFile() { result = this.getContainer() }
|
||||
|
||||
/** Gets the start line of this location. */
|
||||
/** Gets the 1-based line number (inclusive) where this location starts. */
|
||||
int getStartLine() { this.fullLocationInfo(_, result, _, _, _) }
|
||||
|
||||
/** Gets the start column of this location. */
|
||||
/** Gets the 1-based column number (inclusive) where this location starts. */
|
||||
int getStartColumn() { this.fullLocationInfo(_, _, result, _, _) }
|
||||
|
||||
/** Gets the end line of this location. */
|
||||
/** Gets the 1-based line number (inclusive) where this location ends. */
|
||||
int getEndLine() { this.fullLocationInfo(_, _, _, result, _) }
|
||||
|
||||
/** Gets the end column of this location. */
|
||||
/** Gets the 1-based column number (inclusive) where this location ends. */
|
||||
int getEndColumn() { this.fullLocationInfo(_, _, _, _, result) }
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern |
|
||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | inline |
|
||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | inline |
|
||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | is_constexpr |
|
||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | is_constexpr |
|
||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | public |
|
||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | public |
|
||||
| Function | specifiers2pp.cpp:33:5:33:18 | fun | fun | public |
|
||||
@@ -69,6 +71,8 @@
|
||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern |
|
||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | inline |
|
||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | inline |
|
||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | is_constexpr |
|
||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | is_constexpr |
|
||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | public |
|
||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | public |
|
||||
| Function | specifiers2pp.cpp:40:12:40:18 | someFun | someFun | extern |
|
||||
|
||||
@@ -38,16 +38,16 @@ class Location extends @location {
|
||||
/** Gets a textual representation of this location. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the start line of this location. */
|
||||
/** Gets the 1-based line number (inclusive) where this location starts. */
|
||||
final int getStartLine() { this.hasLocationInfo(_, result, _, _, _) }
|
||||
|
||||
/** Gets the end line of this location. */
|
||||
/** Gets the 1-based line number (inclusive) where this location ends. */
|
||||
final int getEndLine() { this.hasLocationInfo(_, _, _, result, _) }
|
||||
|
||||
/** Gets the start column of this location. */
|
||||
/** Gets the 1-based column number (inclusive) where this location starts. */
|
||||
final int getStartColumn() { this.hasLocationInfo(_, _, result, _, _) }
|
||||
|
||||
/** Gets the end column of this location. */
|
||||
/** Gets the 1-based column number (inclusive) where this location ends. */
|
||||
final int getEndColumn() { this.hasLocationInfo(_, _, _, _, result) }
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ We could then write this query to find all ``@SuppressWarnings`` annotations att
|
||||
anntp.hasQualifiedName("java.lang", "SuppressWarnings")
|
||||
select ann, ann.getValue("value")
|
||||
|
||||
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/632150601>`__. Several of the LGTM.com demo projects use the ``@SuppressWarnings`` annotation. Looking at the ``value``\ s of the annotation element returned by the query, we can see that the *apache/activemq* project uses the ``"rawtypes"`` value described above.
|
||||
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/1775658606775222283/>`__. Several of the LGTM.com demo projects use the ``@SuppressWarnings`` annotation. Looking at the ``value``\ s of the annotation element returned by the query, we can see that the *apache/activemq* project uses the ``"rawtypes"`` value described above.
|
||||
|
||||
As another example, this query finds all annotation types that only have a single annotation element, which has name ``value``:
|
||||
|
||||
@@ -64,7 +64,7 @@ As another example, this query finds all annotation types that only have a singl
|
||||
)
|
||||
select anntp
|
||||
|
||||
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/669220001>`__.
|
||||
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/2145264152490258283/>`__.
|
||||
|
||||
Example: Finding missing ``@Override`` annotations
|
||||
--------------------------------------------------
|
||||
@@ -122,7 +122,7 @@ This makes it very easy to write our query for finding methods that override ano
|
||||
not overriding.getAnAnnotation() instanceof OverrideAnnotation
|
||||
select overriding, "Method overrides another method, but does not have an @Override annotation."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1505752756202/>`__. In practice, this query may yield many results from compiled library code, which aren't very interesting. It's therefore a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/7419756266089837339/>`__. In practice, this query may yield many results from compiled library code, which aren't very interesting. It's therefore a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available.
|
||||
|
||||
Example: Finding calls to deprecated methods
|
||||
--------------------------------------------
|
||||
@@ -192,13 +192,13 @@ For instance, consider this slightly updated example:
|
||||
.. code-block:: java
|
||||
|
||||
class A {
|
||||
@Deprecated void m() {}
|
||||
@Deprecated void m() {}
|
||||
|
||||
@Deprecated void n() {
|
||||
m();
|
||||
}
|
||||
@Deprecated void n() {
|
||||
m();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecated")
|
||||
@SuppressWarnings("deprecated")
|
||||
void r() {
|
||||
m();
|
||||
}
|
||||
@@ -235,7 +235,7 @@ Now we can extend our query to filter out calls in methods carrying a ``Suppress
|
||||
and not call.getCaller().getAnAnnotation() instanceof SuppressDeprecationWarningAnnotation
|
||||
select call, "This call invokes a deprecated method."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/665760001>`__. It's fairly common for projects to contain calls to methods that appear to be deprecated.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8706367340403790260/>`__. It's fairly common for projects to contain calls to methods that appear to be deprecated.
|
||||
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
@@ -78,7 +78,7 @@ We can use the ``Callable`` class to write a query that finds methods that are n
|
||||
where not exists(Callable caller | caller.polyCalls(callee))
|
||||
select callee
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/665280012/>`__. This simple query typically returns a large number of results.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8376915232270534450/>`__. This simple query typically returns a large number of results.
|
||||
|
||||
.. pull-quote::
|
||||
|
||||
@@ -97,7 +97,7 @@ Running this query on a typical Java project results in lots of hits in the Java
|
||||
callee.getCompilationUnit().fromSource()
|
||||
select callee, "Not called."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/668510015/>`__. This change reduces the number of results returned for most projects.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8711624074465690976/>`__. This change reduces the number of results returned for most projects.
|
||||
|
||||
We might also notice several unused methods with the somewhat strange name ``<clinit>``: these are class initializers; while they are not explicitly called anywhere in the code, they are called implicitly whenever the surrounding class is loaded. Hence it makes sense to exclude them from our query. While we are at it, we can also exclude finalizers, which are similarly invoked implicitly:
|
||||
|
||||
@@ -111,7 +111,7 @@ We might also notice several unused methods with the somewhat strange name ``<cl
|
||||
not callee.hasName("<clinit>") and not callee.hasName("finalize")
|
||||
select callee, "Not called."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/672230002/>`__. This also reduces the number of results returned by most projects.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/925473733866047471/>`__. This also reduces the number of results returned by most projects.
|
||||
|
||||
We may also want to exclude public methods from our query, since they may be external API entry points:
|
||||
|
||||
@@ -126,7 +126,7 @@ We may also want to exclude public methods from our query, since they may be ext
|
||||
not callee.isPublic()
|
||||
select callee, "Not called."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/667290016/>`__. This should have a more noticeable effect on the number of results returned.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/6284320987237954610/>`__. This should have a more noticeable effect on the number of results returned.
|
||||
|
||||
A further special case is non-public default constructors: in the singleton pattern, for example, a class is provided with private empty default constructor to prevent it from being instantiated. Since the very purpose of such constructors is their not being called, they should not be flagged up:
|
||||
|
||||
@@ -142,7 +142,7 @@ A further special case is non-public default constructors: in the singleton patt
|
||||
not callee.(Constructor).getNumberOfParameters() = 0
|
||||
select callee, "Not called."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/673060008/>`__. This change has a large effect on the results for some projects but little effect on the results for others. Use of this pattern varies widely between different projects.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/2625028545869146918/>`__. This change has a large effect on the results for some projects but little effect on the results for others. Use of this pattern varies widely between different projects.
|
||||
|
||||
Finally, on many Java projects there are methods that are invoked indirectly by reflection. So, while there are no calls invoking these methods, they are, in fact, used. It is in general very hard to identify such methods. A very common special case, however, is JUnit test methods, which are reflectively invoked by a test runner. The CodeQL library for Java has support for recognizing test classes of JUnit and other testing frameworks, which we can employ to filter out methods defined in such classes:
|
||||
|
||||
@@ -159,7 +159,7 @@ Finally, on many Java projects there are methods that are invoked indirectly by
|
||||
not callee.getDeclaringType() instanceof TestClass
|
||||
select callee, "Not called."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/665760002/>`__. This should give a further reduction in the number of results returned.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/2055862421970264112/>`__. This should give a further reduction in the number of results returned.
|
||||
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
@@ -42,7 +42,7 @@ We'll start by writing a query that finds less-than expressions (CodeQL class ``
|
||||
expr.getRightOperand().getType().hasName("long")
|
||||
select expr
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/672320008/>`__. This query usually finds results on most projects.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/490866529746563234/>`__. This query usually finds results on most projects.
|
||||
|
||||
Notice that we use the predicate ``getType`` (available on all subclasses of ``Expr``) to determine the type of the operands. Types, in turn, define the ``hasName`` predicate, which allows us to identify the primitive types ``int`` and ``long``. As it stands, this query finds *all* less-than expressions comparing ``int`` and ``long``, but in fact we are only interested in comparisons that are part of a loop condition. Also, we want to filter out comparisons where either operand is constant, since these are less likely to be real bugs. The revised query looks like this:
|
||||
|
||||
@@ -57,7 +57,7 @@ Notice that we use the predicate ``getType`` (available on all subclasses of ``E
|
||||
not expr.getAnOperand().isCompileTimeConstant()
|
||||
select expr
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/690010001/>`__. Notice that fewer results are found.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/4315986481180063825/>`__. Notice that fewer results are found.
|
||||
|
||||
The class ``LoopStmt`` is a common superclass of all loops, including, in particular, ``for`` loops as in our example above. While different kinds of loops have different syntax, they all have a loop condition, which can be accessed through predicate ``getCondition``. We use the reflexive transitive closure operator ``*`` applied to the ``getAChildExpr`` predicate to express the requirement that ``expr`` should be nested inside the loop condition. In particular, it can be the loop condition itself.
|
||||
|
||||
@@ -120,7 +120,7 @@ Now we rewrite our query to make use of these new classes:
|
||||
not expr.getAnOperand().isCompileTimeConstant()
|
||||
select expr
|
||||
|
||||
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/1951710018/lang:java/>`__.
|
||||
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/506868054626167462/>`__.
|
||||
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
@@ -49,7 +49,7 @@ Types
|
||||
|
||||
Class ``Type`` has a number of subclasses for representing different kinds of types:
|
||||
|
||||
- ``PrimitiveType`` represents a `primitive type <http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html>`__, that is, one of ``boolean``, ``byte``, ``char``, ``double``, ``float``, ``int``, ``long``, ``short``; QL also classifies ``void`` and ``<nulltype>`` (the type of the ``null`` literal) as primitive types.
|
||||
- ``PrimitiveType`` represents a `primitive type <https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html>`__, that is, one of ``boolean``, ``byte``, ``char``, ``double``, ``float``, ``int``, ``long``, ``short``; QL also classifies ``void`` and ``<nulltype>`` (the type of the ``null`` literal) as primitive types.
|
||||
- ``RefType`` represents a reference (that is, non-primitive) type; it in turn has several subclasses:
|
||||
|
||||
- ``Class`` represents a Java class.
|
||||
@@ -68,7 +68,7 @@ For example, the following query finds all variables of type ``int`` in the prog
|
||||
pt.hasName("int")
|
||||
select v
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/660700018/>`__. You're likely to get many results when you run this query because most projects contain many variables of type ``int``.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/860076406167044435/>`__. You're likely to get many results when you run this query because most projects contain many variables of type ``int``.
|
||||
|
||||
Reference types are also categorized according to their declaration scope:
|
||||
|
||||
@@ -85,15 +85,15 @@ For instance, this query finds all top-level types whose name is not the same as
|
||||
where tl.getName() != tl.getCompilationUnit().getName()
|
||||
select tl
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/674620002/>`__. This pattern is seen in many projects. When we ran it on the LGTM.com demo projects, most of the projects had at least one instance of this problem in the source code. There were many more instances in the files referenced by the source code.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/4340983612585284460/>`__. This pattern is seen in many projects. When we ran it on the LGTM.com demo projects, most of the projects had at least one instance of this problem in the source code. There were many more instances in the files referenced by the source code.
|
||||
|
||||
Several more specialized classes are available as well:
|
||||
|
||||
- ``TopLevelClass`` represents a class declared at the top-level of a compilation unit.
|
||||
- ``NestedClass`` represents `a class declared inside another type <http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html>`__, such as:
|
||||
- ``NestedClass`` represents `a class declared inside another type <https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html>`__, such as:
|
||||
|
||||
- A ``LocalClass``, which is `a class declared inside a method or constructor <http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html>`__.
|
||||
- An ``AnonymousClass``, which is an `anonymous class <http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html>`__.
|
||||
- A ``LocalClass``, which is `a class declared inside a method or constructor <https://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html>`__.
|
||||
- An ``AnonymousClass``, which is an `anonymous class <https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html>`__.
|
||||
|
||||
Finally, the library also has a number of singleton classes that wrap frequently used Java standard library classes: ``TypeObject``, ``TypeCloneable``, ``TypeRuntime``, ``TypeSerializable``, ``TypeString``, ``TypeSystem`` and ``TypeClass``. Each CodeQL class represents the standard Java class suggested by its name.
|
||||
|
||||
@@ -107,7 +107,7 @@ As an example, we can write a query that finds all nested classes that directly
|
||||
where nc.getASupertype() instanceof TypeObject
|
||||
select nc
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/672230026/>`__. You're likely to get many results when you run this query because many projects include nested classes that extend ``Object`` directly.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8482509736206423238/>`__. You're likely to get many results when you run this query because many projects include nested classes that extend ``Object`` directly.
|
||||
|
||||
Generics
|
||||
~~~~~~~~
|
||||
@@ -141,7 +141,7 @@ For instance, we could use the following query to find all parameterized instanc
|
||||
pt.getSourceDeclaration() = map
|
||||
select pt
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/660700019/>`__. None of the LGTM.com demo projects contain parameterized instances of ``java.util.Map`` in their source code, but they all have results in reference files.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/7863873821043873550/>`__. None of the LGTM.com demo projects contain parameterized instances of ``java.util.Map`` in their source code, but they all have results in reference files.
|
||||
|
||||
In general, generic types may restrict which types a type parameter can be bound to. For instance, a type of maps from strings to numbers could be declared as follows:
|
||||
|
||||
@@ -164,7 +164,7 @@ As an example, the following query finds all type variables with type bound ``Nu
|
||||
tb.getType().hasQualifiedName("java.lang", "Number")
|
||||
select tv
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/690010016/>`__. When we ran it on the LGTM.com demo projects, the *neo4j/neo4j*, *gradle/gradle* and *hibernate/hibernate-orm* projects all contained examples of this pattern.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/6740696080876162817/>`__. When we ran it on the LGTM.com demo projects, the *neo4j/neo4j*, *hibernate/hibernate-orm* and *apache/hadoop* projects all contained examples of this pattern.
|
||||
|
||||
For dealing with legacy code that is unaware of generics, every generic type has a "raw" version without any type parameters. In the CodeQL libraries, raw types are represented using class ``RawType``, which has the expected subclasses ``RawClass`` and ``RawInterface``. Again, there is a predicate ``getSourceDeclaration`` for obtaining the corresponding generic type. As an example, we can find variables of (raw) type ``Map``:
|
||||
|
||||
@@ -177,7 +177,7 @@ For dealing with legacy code that is unaware of generics, every generic type has
|
||||
rt.getSourceDeclaration().hasQualifiedName("java.util", "Map")
|
||||
select v
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/686320008/>`__. Many projects have variables of raw type ``Map``.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/4032913402499547882/>`__. Many projects have variables of raw type ``Map``.
|
||||
|
||||
For example, in the following code snippet this query would find ``m1``, but not ``m2``:
|
||||
|
||||
@@ -186,7 +186,7 @@ For example, in the following code snippet this query would find ``m1``, but not
|
||||
Map m1 = new HashMap();
|
||||
Map<String, String> m2 = new HashMap<String, String>();
|
||||
|
||||
Finally, variables can be declared to be of a `wildcard type <http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html>`__:
|
||||
Finally, variables can be declared to be of a `wildcard type <https://docs.oracle.com/javase/tutorial/java/generics/wildcards.html>`__:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
@@ -201,7 +201,7 @@ For more information on working with types, see the :doc:`article on Java types
|
||||
Variables
|
||||
~~~~~~~~~
|
||||
|
||||
Class ``Variable`` represents a variable `in the Java sense <http://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html>`__, which is either a member field of a class (whether static or not), or a local variable, or a parameter. Consequently, there are three subclasses catering to these special cases:
|
||||
Class ``Variable`` represents a variable `in the Java sense <https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html>`__, which is either a member field of a class (whether static or not), or a local variable, or a parameter. Consequently, there are three subclasses catering to these special cases:
|
||||
|
||||
- ``Field`` represents a Java field.
|
||||
- ``LocalVariableDecl`` represents a local variable.
|
||||
@@ -228,7 +228,7 @@ For example, the following query finds all expressions whose parents are ``retur
|
||||
where e.getParent() instanceof ReturnStmt
|
||||
select e
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/668700463/>`__. Many projects have examples of ``return`` statements with child statements.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1947757851560375919/>`__. Many projects have examples of ``return`` statements with child expressions.
|
||||
|
||||
Therefore, if the program contains a return statement ``return x + y;``, this query will return ``x + y``.
|
||||
|
||||
@@ -242,7 +242,7 @@ As another example, the following query finds statements whose parent is an ``if
|
||||
where s.getParent() instanceof IfStmt
|
||||
select s
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/670720173/>`__. Many projects have examples of ``if`` statements with child statements.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1989464153689219612/>`__. Many projects have examples of ``if`` statements with child statements.
|
||||
|
||||
This query will find both ``then`` branches and ``else`` branches of all ``if`` statements in the program.
|
||||
|
||||
@@ -256,7 +256,7 @@ Finally, here is a query that finds method bodies:
|
||||
where s.getParent() instanceof Method
|
||||
select s
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/663740023/>`__. Most projects have many method bodies.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1016821702972128245/>`__. Most projects have many method bodies.
|
||||
|
||||
As these examples show, the parent node of an expression is not always an expression: it may also be a statement, for example, an ``IfStmt``. Similarly, the parent node of a statement is not always a statement: it may also be a method or a constructor. To capture this, the QL Java library provides two abstract class ``ExprParent`` and ``StmtParent``, the former representing any node that may be the parent node of an expression, and the latter any node that may be the parent node of a statement.
|
||||
|
||||
@@ -265,7 +265,7 @@ For more information on working with AST classes, see the :doc:`article on overf
|
||||
Metadata
|
||||
--------
|
||||
|
||||
Java programs have several kinds of metadata, in addition to the program code proper. In particular, there are `annotations <http://docs.oracle.com/javase/tutorial/java/annotations/>`__ and `Javadoc <http://en.wikipedia.org/wiki/Javadoc>`__ comments. Since this metadata is interesting both for enhancing code analysis and as an analysis subject in its own right, the QL library defines classes for accessing it.
|
||||
Java programs have several kinds of metadata, in addition to the program code proper. In particular, there are `annotations <https://docs.oracle.com/javase/tutorial/java/annotations/>`__ and `Javadoc <https://en.wikipedia.org/wiki/Javadoc>`__ comments. Since this metadata is interesting both for enhancing code analysis and as an analysis subject in its own right, the QL library defines classes for accessing it.
|
||||
|
||||
For annotations, class ``Annotatable`` is a superclass of all program elements that can be annotated. This includes packages, reference types, fields, methods, constructors, and local variable declarations. For every such element, its predicate ``getAnAnnotation`` allows you to retrieve any annotations the element may have. For example, the following query finds all annotations on constructors:
|
||||
|
||||
@@ -276,7 +276,7 @@ For annotations, class ``Annotatable`` is a superclass of all program elements t
|
||||
from Constructor c
|
||||
select c.getAnAnnotation()
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/665620008/>`__. The LGTM.com demo projects all use annotations, you can see examples where they are used to suppress warnings and mark code as deprecated.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/3206112561297137365/>`__. The LGTM.com demo projects all use annotations, you can see examples where they are used to suppress warnings and mark code as deprecated.
|
||||
|
||||
These annotations are represented by class ``Annotation``. An annotation is simply an expression whose type is an ``AnnotationType``. For example, you can amend this query so that it only reports deprecated constructors:
|
||||
|
||||
@@ -290,7 +290,7 @@ These annotations are represented by class ``Annotation``. An annotation is simp
|
||||
anntp.hasQualifiedName("java.lang", "Deprecated")
|
||||
select ann
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/659662167/>`__. Only constructors with the ``@deprecated`` annotation are reported this time.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/5393027107459215059/>`__. Only constructors with the ``@Deprecated`` annotation are reported this time.
|
||||
|
||||
For more information on working with annotations, see the :doc:`article on annotations <annotations>`.
|
||||
|
||||
@@ -305,7 +305,7 @@ For Javadoc, class ``Element`` has a member predicate ``getDoc`` that returns a
|
||||
jdoc = f.getDoc().getJavadoc()
|
||||
select jdoc
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/663330296/>`__. You can see this pattern in many projects.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/6022769142134600659/>`__. You can see this pattern in many projects.
|
||||
|
||||
Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocElement`` nodes, which can be traversed using member predicates ``getAChild`` and ``getParent``. For instance, you could edit the query so that it finds all ``@author`` tags in Javadoc comments on private fields:
|
||||
|
||||
@@ -319,7 +319,7 @@ Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocEle
|
||||
at.getParent+() = jdoc
|
||||
select at
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/670490015/>`__. None of the LGTM.com demo projects uses the ``@author`` tag on private fields.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/2510220694395289111/>`__. None of the LGTM.com demo projects uses the ``@author`` tag on private fields.
|
||||
|
||||
.. pull-quote::
|
||||
|
||||
@@ -336,7 +336,7 @@ The standard QL Java library provides extensive support for computing metrics on
|
||||
|
||||
Altogether, there are six such classes: ``MetricElement``, ``MetricPackage``, ``MetricRefType``, ``MetricField``, ``MetricCallable``, and ``MetricStmt``. The corresponding element classes each provide a member predicate ``getMetrics`` that can be used to obtain an instance of the delegate class, on which metric computations can then be performed.
|
||||
|
||||
For example, the following query finds methods with a `cyclomatic complexity <http://en.wikipedia.org/wiki/Cyclomatic_complexity>`__ greater than 40:
|
||||
For example, the following query finds methods with a `cyclomatic complexity <https://en.wikipedia.org/wiki/Cyclomatic_complexity>`__ greater than 40:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -347,7 +347,7 @@ For example, the following query finds methods with a `cyclomatic complexity <ht
|
||||
mc.getCyclomaticComplexity() > 40
|
||||
select m
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/670720174/>`__. Most large projects include some methods with a very high cyclomatic complexity. These methods are likely to be difficult to understand and test.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/6566950741051181919/>`__. Most large projects include some methods with a very high cyclomatic complexity. These methods are likely to be difficult to understand and test.
|
||||
|
||||
Call graph
|
||||
----------
|
||||
@@ -367,7 +367,7 @@ We can use predicate ``Call.getCallee`` to find out which method or constructor
|
||||
m.hasName("println")
|
||||
select c
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/669220009/>`__. The LGTM.com demo projects all include many calls to methods of this name.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/5861255162551917595/>`__. The LGTM.com demo projects all include many calls to methods of this name.
|
||||
|
||||
Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So we can find methods and constructors that are never called using this query:
|
||||
|
||||
@@ -379,7 +379,7 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So
|
||||
where not exists(c.getAReference())
|
||||
select c
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/666680036/>`__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph <call-graph>`.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/7261739919657747703/>`__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph <call-graph>`.
|
||||
|
||||
For more information about callables and calls, see the :doc:`article on the call graph <call-graph>`.
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ Now we can write a query for finding all callables ``c`` and ``@throws`` tags ``
|
||||
not mayThrow(c, exn)
|
||||
select tt, "Spurious @throws tag."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1505752646058/>`__. This finds several results in the LGTM.com demo projects.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1258570917227966396/>`__. This finds several results in the LGTM.com demo projects.
|
||||
|
||||
Improvements
|
||||
~~~~~~~~~~~~
|
||||
@@ -214,7 +214,7 @@ The first case can be covered by changing ``getDocumentedException`` to use the
|
||||
(result.hasName(tt.getExceptionName()) and visibleIn(tt.getFile(), result))
|
||||
}
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1505751136101/>`__. This finds many fewer, more interesting results in the LGTM.com demo projects.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8016848987103345329/>`__. This finds many fewer, more interesting results in the LGTM.com demo projects.
|
||||
|
||||
Currently, ``visibleIn`` only considers single-type imports, but you could extend it with support for other kinds of imports.
|
||||
|
||||
|
||||
@@ -54,17 +54,17 @@ In our example, the expression statement starts at line 5, column 3 (the first t
|
||||
|
||||
Class ``File`` defines these member predicates:
|
||||
|
||||
- ``getFullName`` returns the fully qualified name of the file.
|
||||
- ``getAbsolutePath`` returns the fully qualified name of the file.
|
||||
- ``getRelativePath`` returns the path of the file relative to the base directory of the source code.
|
||||
- ``getExtension`` returns the extension of the file.
|
||||
- ``getShortName`` returns the base name of the file, without its extension.
|
||||
- ``getStem`` returns the base name of the file, without its extension.
|
||||
|
||||
In our example, assume file ``A.java`` is located in directory ``/home/testuser/code/pkg``, where ``/home/testuser/code`` is the base directory of the program being analyzed. Then, a ``File`` object for ``A.java`` returns:
|
||||
|
||||
- ``getFullName`` is ``/home/testuser/code/pkg/A.java``.
|
||||
- ``getAbsolutePath`` is ``/home/testuser/code/pkg/A.java``.
|
||||
- ``getRelativePath`` is ``pkg/A.java``.
|
||||
- ``getExtension`` is ``java``.
|
||||
- ``getShortName`` is ``A``.
|
||||
- ``getStem`` is ``A``.
|
||||
|
||||
Determining white space around an operator
|
||||
------------------------------------------
|
||||
@@ -110,7 +110,7 @@ Here's a first version of our query:
|
||||
wsinner > wsouter
|
||||
select outer, "Whitespace around nested operators contradicts precedence."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/672230027/>`__. This query is likely to find results on most projects.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8141155897270480914/>`__. This query is likely to find results on most projects.
|
||||
|
||||
The first conjunct of the ``where`` clause restricts ``inner`` to be an operand of ``outer``, the second conjunct binds ``wsinner`` and ``wsouter``, while the last conjunct selects the suspicious cases.
|
||||
|
||||
@@ -141,9 +141,9 @@ Note that our predicate ``operatorWS`` computes the **total** amount of white sp
|
||||
wsinner > wsouter
|
||||
select outer, "Whitespace around nested operators contradicts precedence."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/665761067/>`__. Any results will be refined by our changes to the query.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/3151720037708691205/>`__. Any results will be refined by our changes to the query.
|
||||
|
||||
Another source of false positives are associative operators: in an expression of the form ``x + y+z``, the first plus is syntactically nested inside the second, since + in Java associates to the left; hence the expression is flagged as suspicious. But since + is associative to begin with, it does not matter which way around the operators are nested, so this is a false positive.To exclude these cases, let us define a new class identifying binary expressions with an associative operator:
|
||||
Another source of false positives are associative operators: in an expression of the form ``x + y+z``, the first plus is syntactically nested inside the second, since + in Java associates to the left; hence the expression is flagged as suspicious. But since + is associative to begin with, it does not matter which way around the operators are nested, so this is a false positive. To exclude these cases, let us define a new class identifying binary expressions with an associative operator:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -173,9 +173,9 @@ Now we can extend our query to discard results where the outer and the inner exp
|
||||
wsinner > wsouter
|
||||
select outer, "Whitespace around nested operators contradicts precedence."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/659662169/>`__.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/5714614966569401039/>`__.
|
||||
|
||||
Notice that we again use ``getOp``, this time to determine whether two binary expressions have the same operator. Running our improved query now finds the Java standard library bug described in the Overview. It also flags up the following suspicious code in `Hadoop HBase <http://hbase.apache.org/>`__:
|
||||
Notice that we again use ``getOp``, this time to determine whether two binary expressions have the same operator. Running our improved query now finds the Java standard library bug described in the Overview. It also flags up the following suspicious code in `Hadoop HBase <https://hbase.apache.org/>`__:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ To determine ancestor types (including immediate super types, and also *their* s
|
||||
where B.hasName("B")
|
||||
select B.getASupertype+()
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/674620010/>`__. If this query were run on the example snippet above, the query would return ``A``, ``I``, and ``java.lang.Object``.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1506430738755934285/>`__. If this query were run on the example snippet above, the query would return ``A``, ``I``, and ``java.lang.Object``.
|
||||
|
||||
.. pull-quote::
|
||||
|
||||
@@ -78,7 +78,7 @@ This recipe is not too difficult to translate into a query:
|
||||
target.getElementType().(RefType).getASupertype+() = source.getElementType()
|
||||
select ce, "Potentially problematic array downcast."
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/666680038/>`__. Many projects return results for this query.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8378564667548381869/>`__. Many projects return results for this query.
|
||||
|
||||
Note that by casting ``target.getElementType()`` to a ``RefType``, we eliminate all cases where the element type is a primitive type, that is, ``target`` is an array of primitive type: the problem we are looking for cannot arise in that case. Unlike in Java, a cast in QL never fails: if an expression cannot be cast to the desired type, it is simply excluded from the query results, which is exactly what we want.
|
||||
|
||||
@@ -97,7 +97,7 @@ In code that does not use generics, this method is often used in the following w
|
||||
|
||||
Here, ``l`` has the raw type ``List``, so ``l.toArray`` has return type ``Object[]``, independent of the type of its argument array. Hence the cast goes from ``Object[]`` to ``A[]`` and will be flagged as problematic by our query, although at runtime this cast can never go wrong.
|
||||
|
||||
To identify these cases, we can create two CodeQL classes that represent, respectively, the ``Collection.toArray`` class, and calls to this method or any method that overrides it:
|
||||
To identify these cases, we can create two CodeQL classes that represent, respectively, the ``Collection.toArray`` method, and calls to this method or any method that overrides it:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -148,7 +148,7 @@ Example: Finding mismatched contains checks
|
||||
|
||||
We'll now develop a query that finds uses of ``Collection.contains`` where the type of the queried element is unrelated to the element type of the collection, which guarantees that the test will always return ``false``.
|
||||
|
||||
For example, `Apache Zookeeper <http://zookeeper.apache.org/>`__ used to have a snippet of code similar to the following in class ``QuorumPeerConfig``:
|
||||
For example, `Apache Zookeeper <https://zookeeper.apache.org/>`__ used to have a snippet of code similar to the following in class ``QuorumPeerConfig``:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
@@ -267,7 +267,7 @@ Now we are ready to write a first version of our query:
|
||||
not haveCommonDescendant(collEltType, argType)
|
||||
select juccc, "Element type " + collEltType + " is incompatible with argument type " + argType
|
||||
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1505750556420/>`__.
|
||||
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/7947831380785106258/>`__.
|
||||
|
||||
Improvements
|
||||
~~~~~~~~~~~~
|
||||
@@ -294,7 +294,7 @@ Adding these three improvements, our final query becomes:
|
||||
not argType.hasName("<nulltype>")
|
||||
select juccc, "Element type " + collEltType + " is incompatible with argument type " + argType
|
||||
|
||||
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/1505753056300/>`__.
|
||||
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/8846334903769538099/>`__.
|
||||
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
@@ -90,16 +90,16 @@ class Top extends @top {
|
||||
|
||||
/** A location maps language elements to positions in source files. */
|
||||
class Location extends @location {
|
||||
/** Gets the line number where this location starts. */
|
||||
/** Gets the 1-based line number (inclusive) where this location starts. */
|
||||
int getStartLine() { locations_default(this, _, result, _, _, _) }
|
||||
|
||||
/** Gets the column number where this location starts. */
|
||||
/** Gets the 1-based column number (inclusive) where this location starts. */
|
||||
int getStartColumn() { locations_default(this, _, _, result, _, _) }
|
||||
|
||||
/** Gets the line number where this location ends. */
|
||||
/** Gets the 1-based line number (inclusive) where this location ends. */
|
||||
int getEndLine() { locations_default(this, _, _, _, result, _) }
|
||||
|
||||
/** Gets the column number where this location ends. */
|
||||
/** Gets the 1-based column number (inclusive) where this location ends. */
|
||||
int getEndColumn() { locations_default(this, _, _, _, _, result) }
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,6 +60,12 @@ class Expr extends ExprParent, @expr {
|
||||
/** Gets the statement containing this expression, if any. */
|
||||
Stmt getEnclosingStmt() { statementEnclosingExpr(this, result) }
|
||||
|
||||
/**
|
||||
* Gets a statement that directly or transitively contains this expression, if any.
|
||||
* This is equivalent to `this.getEnclosingStmt().getEnclosingStmt*()`.
|
||||
*/
|
||||
Stmt getAnEnclosingStmt() { result = this.getEnclosingStmt().getEnclosingStmt*() }
|
||||
|
||||
/** Gets a child of this expression. */
|
||||
Expr getAChildExpr() { exprs(result, _, _, this, _) }
|
||||
|
||||
@@ -1237,7 +1243,7 @@ class VariableAssign extends VariableUpdate {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source of this assignment, if any.
|
||||
* Gets the source (right-hand side) of this assignment, if any.
|
||||
*
|
||||
* An initialization in a `CatchClause` or `EnhancedForStmt` is implicit and
|
||||
* does not have a source.
|
||||
|
||||
@@ -79,7 +79,7 @@ abstract class JavadocElement extends @javadocElement, Top {
|
||||
abstract string getText();
|
||||
}
|
||||
|
||||
/** A Javadoc tag. */
|
||||
/** A Javadoc block tag. This does not include inline tags. */
|
||||
class JavadocTag extends JavadocElement, JavadocParent, @javadocTag {
|
||||
/** Gets the name of this Javadoc tag. */
|
||||
string getTagName() { javadocTag(this, result, _, _) }
|
||||
|
||||
@@ -196,6 +196,12 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
|
||||
method.hasName("entry") and
|
||||
arg = 1
|
||||
)
|
||||
or
|
||||
method.getDeclaringType().hasQualifiedName("java.util", "Arrays") and
|
||||
(
|
||||
method.hasName(["copyOf", "copyOfRange", "spliterator", "stream"]) and
|
||||
arg = 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,6 +229,13 @@ private predicate taintPreservingArgToArg(Method method, int input, int output)
|
||||
or
|
||||
method.hasName("replaceAll") and input = 2 and output = 0
|
||||
)
|
||||
or
|
||||
method.getDeclaringType().hasQualifiedName("java.util", "Arrays") and
|
||||
(
|
||||
method.hasName("fill") and
|
||||
output = 0 and
|
||||
input = method.getNumberOfParameters() - 1
|
||||
)
|
||||
}
|
||||
|
||||
private predicate argToQualifierStep(Expr tracked, Expr sink) {
|
||||
@@ -236,9 +249,18 @@ private predicate argToQualifierStep(Expr tracked, Expr sink) {
|
||||
|
||||
/** Access to a method that passes taint from an argument. */
|
||||
private predicate argToMethodStep(Expr tracked, MethodAccess sink) {
|
||||
exists(int i |
|
||||
taintPreservingArgumentToMethod(sink.getMethod(), i) and
|
||||
tracked = sink.getArgument(i)
|
||||
exists(Method m |
|
||||
m = sink.getMethod() and
|
||||
(
|
||||
exists(int i |
|
||||
taintPreservingArgumentToMethod(m, i) and
|
||||
tracked = sink.getArgument(i)
|
||||
)
|
||||
or
|
||||
m.getDeclaringType().hasQualifiedName("java.util", "Arrays") and
|
||||
m.hasName("asList") and
|
||||
tracked = sink.getAnArgument()
|
||||
)
|
||||
)
|
||||
or
|
||||
taintPreservingArgumentToMethod(sink.getMethod()) and
|
||||
|
||||
@@ -9,9 +9,9 @@ private predicate fileRead(VarAccess fileAccess, Expr fileReadingExpr) {
|
||||
cie = fileReadingExpr and
|
||||
cie.getArgument(0) = fileAccess
|
||||
|
|
||||
cie.getConstructedType().hasQualifiedName("java.io", "RandomAccessFile") or
|
||||
cie.getConstructedType().hasQualifiedName("java.io", "FileReader") or
|
||||
cie.getConstructedType().hasQualifiedName("java.io", "FileInputStream")
|
||||
cie
|
||||
.getConstructedType()
|
||||
.hasQualifiedName("java.io", ["RandomAccessFile", "FileReader", "FileInputStream"])
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma, Method filesMethod |
|
||||
@@ -22,13 +22,9 @@ private predicate fileRead(VarAccess fileAccess, Expr fileReadingExpr) {
|
||||
// represented by the first argument.
|
||||
filesMethod.getDeclaringType().hasQualifiedName("java.nio.file", "Files") and
|
||||
fileAccess = ma.getArgument(0) and
|
||||
(
|
||||
filesMethod.hasName("readAllBytes") or
|
||||
filesMethod.hasName("readAllLines") or
|
||||
filesMethod.hasName("newBufferedReader") or
|
||||
filesMethod.hasName("newInputReader") or
|
||||
filesMethod.hasName("newByteChannel")
|
||||
)
|
||||
filesMethod
|
||||
.hasName(["readAllBytes", "readAllLines", "readString", "lines", "newBufferedReader",
|
||||
"newInputStream", "newByteChannel"])
|
||||
)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.2.3
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/shiro-core-1.5.2:${testdir}/../../../stubs/spring-ldap-2.3.2
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/shiro-core-1.5.2:${testdir}/../../../../stubs/spring-ldap-2.3.2
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/ognl-3.2.14:${testdir}/../../../stubs/struts2-core-2.5.22
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/ognl-3.2.14:${testdir}/../../../stubs/struts2-core-2.5.22
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
package org.springframework.ldap.core;
|
||||
|
||||
public interface ContextMapper<T> {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package org.springframework.ldap.core;
|
||||
|
||||
public interface DirContextOperations {
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package org.springframework.ldap.core;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.naming.Name;
|
||||
import javax.naming.directory.SearchControls;
|
||||
|
||||
import org.springframework.ldap.filter.Filter;
|
||||
|
||||
import org.springframework.ldap.query.LdapQuery;
|
||||
|
||||
public class LdapTemplate implements LdapOperations, InitializingBean {
|
||||
public void authenticate(LdapQuery query, String password) { }
|
||||
|
||||
public boolean authenticate(Name base, String filter, String password) { return true; }
|
||||
|
||||
public <T> List<T> find(Name base, Filter filter, SearchControls searchControls, final Class<T> clazz) { return null; }
|
||||
|
||||
public <T> List<T> find(LdapQuery query, Class<T> clazz) { return null; }
|
||||
|
||||
public <T> T findOne(LdapQuery query, Class<T> clazz) { return null; }
|
||||
|
||||
public void search(String base, String filter, int searchScope, boolean returningObjFlag, NameClassPairCallbackHandler handler) { }
|
||||
|
||||
public void search(final String base, final String filter, final SearchControls controls, NameClassPairCallbackHandler handler) {}
|
||||
|
||||
public void search(final String base, final String filter, final SearchControls controls, NameClassPairCallbackHandler handler, DirContextProcessor processor) {}
|
||||
|
||||
public void search(String base, String filter, NameClassPairCallbackHandler handler) {}
|
||||
|
||||
public <T> List<T> search(String base, String filter, int searchScope, String[] attrs, AttributesMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, int searchScope, AttributesMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, AttributesMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, int searchScope, String[] attrs, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, int searchScope, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, SearchControls controls, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, SearchControls controls, AttributesMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, SearchControls controls, AttributesMapper<T> mapper, DirContextProcessor processor) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, SearchControls controls, ContextMapper<T> mapper, DirContextProcessor processor) { return null; }
|
||||
|
||||
public DirContextOperations searchForContext(LdapQuery query) { return null; }
|
||||
|
||||
public <T> T searchForObject(Name base, String filter, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> T searchForObject(String base, String filter, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> T searchForObject(String base, String filter, SearchControls searchControls, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public Object lookup(final String dn) { return new Object(); }
|
||||
|
||||
public DirContextOperations lookupContext(String dn) { return null; }
|
||||
|
||||
public <T> T findByDn(Name dn, final Class<T> clazz) { return null; }
|
||||
|
||||
public void rename(final Name oldDn, final Name newDn) {}
|
||||
|
||||
public List<String> list(final Name base) { return null; }
|
||||
|
||||
public List<String> listBindings(final Name base) { return null; }
|
||||
|
||||
public void unbind(final String dn) {}
|
||||
|
||||
public void unbind(final String dn, boolean recursive) {}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
package org.springframework.ldap.core;
|
||||
|
||||
public interface NameClassPairCallbackHandler { }
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.springframework.ldap.filter;
|
||||
|
||||
public class EqualsFilter implements Filter {
|
||||
public EqualsFilter(String attribute, String value) { }
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package org.springframework.ldap.filter;
|
||||
|
||||
public interface Filter {
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.springframework.ldap.filter;
|
||||
|
||||
public class HardcodedFilter implements Filter {
|
||||
public HardcodedFilter(String filter) { }
|
||||
public StringBuffer encode(StringBuffer buff) { return buff; }
|
||||
public String toString() { return ""; }
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.springframework.ldap.query;
|
||||
|
||||
public interface ConditionCriteria {
|
||||
ContainerCriteria is(String value);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package org.springframework.ldap.query;
|
||||
|
||||
public interface ContainerCriteria extends LdapQuery {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package org.springframework.ldap.query;
|
||||
|
||||
public interface LdapQuery {
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.springframework.ldap.query;
|
||||
|
||||
import javax.naming.Name;
|
||||
import org.springframework.ldap.filter.Filter;
|
||||
|
||||
public class LdapQueryBuilder {
|
||||
public static LdapQueryBuilder query() { return null; }
|
||||
public LdapQuery filter(String hardcodedFilter) { return null; }
|
||||
public LdapQuery filter(Filter filter) { return null; }
|
||||
public LdapQuery filter(String filterFormat, Object... params) { return null; }
|
||||
public LdapQueryBuilder base(String baseDn) { return this; }
|
||||
public Name base() { return null; }
|
||||
public ConditionCriteria where(String attribute) { return null; }
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.springframework.ldap.support;
|
||||
|
||||
public class LdapEncoder {
|
||||
public static String filterEncode(String value) { return null; }
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package org.springframework.ldap.support;
|
||||
|
||||
import javax.naming.ldap.LdapName;
|
||||
|
||||
public class LdapNameBuilder {
|
||||
public static LdapNameBuilder newInstance() { return null; }
|
||||
public static LdapNameBuilder newInstance(String name) { return null; }
|
||||
|
||||
public LdapNameBuilder add(String name) { return null; }
|
||||
public LdapNameBuilder add(String key, Object value) { return null; }
|
||||
public LdapName build() { return null; }
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.springframework.ldap.support;
|
||||
|
||||
import javax.naming.ldap.LdapName;
|
||||
|
||||
public class LdapUtils {
|
||||
public static LdapName newLdapName(String distinguishedName) { return null; }
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package org.springframework.web.bind.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(value=ElementType.PARAMETER)
|
||||
@Retention(value=RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface RequestParam { }
|
||||
@@ -0,0 +1,23 @@
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
class ArraysTest {
|
||||
public static void taintSteps(String[] source) {
|
||||
Arrays.asList();
|
||||
Arrays.asList("one");
|
||||
Arrays.asList("two", "three");
|
||||
Arrays.copyOf(source, 10);
|
||||
Arrays.copyOfRange(source, 0, 10);
|
||||
Arrays.deepToString(source);
|
||||
Arrays.spliterator(source);
|
||||
Arrays.stream(source);
|
||||
Arrays.toString(source);
|
||||
Arrays.fill(source, "value");
|
||||
Arrays.fill(source, 0, 10, "data");
|
||||
Arrays.parallelPrefix(source, (x, y) -> x + y);
|
||||
Arrays.parallelPrefix(source, 0, 10, (x, y) -> x + y);
|
||||
Arrays.parallelSetAll(source, x -> Integer.toString(x));
|
||||
Arrays.setAll(source, x -> Integer.toString(x));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
| ArraysTest.java:7:17:7:21 | "one" | ArraysTest.java:7:3:7:22 | asList(...) |
|
||||
| ArraysTest.java:7:17:7:21 | "one" | ArraysTest.java:7:3:7:22 | new ..[] { .. } |
|
||||
| ArraysTest.java:8:17:8:21 | "two" | ArraysTest.java:8:3:8:31 | asList(...) |
|
||||
| ArraysTest.java:8:17:8:21 | "two" | ArraysTest.java:8:3:8:31 | new ..[] { .. } |
|
||||
| ArraysTest.java:8:24:8:30 | "three" | ArraysTest.java:8:3:8:31 | asList(...) |
|
||||
| ArraysTest.java:8:24:8:30 | "three" | ArraysTest.java:8:3:8:31 | new ..[] { .. } |
|
||||
| ArraysTest.java:9:17:9:22 | source | ArraysTest.java:9:3:9:27 | copyOf(...) |
|
||||
| ArraysTest.java:10:22:10:27 | source | ArraysTest.java:10:3:10:35 | copyOfRange(...) |
|
||||
| ArraysTest.java:12:22:12:27 | source | ArraysTest.java:12:3:12:28 | spliterator(...) |
|
||||
| ArraysTest.java:13:17:13:22 | source | ArraysTest.java:13:3:13:23 | stream(...) |
|
||||
| ArraysTest.java:15:23:15:29 | "value" | ArraysTest.java:15:15:15:20 | source [post update] |
|
||||
| ArraysTest.java:16:30:16:35 | "data" | ArraysTest.java:16:15:16:20 | source [post update] |
|
||||
| ArraysTest.java:17:43:17:43 | x | ArraysTest.java:17:43:17:47 | ... + ... |
|
||||
| ArraysTest.java:17:47:17:47 | y | ArraysTest.java:17:43:17:47 | ... + ... |
|
||||
| ArraysTest.java:18:50:18:50 | x | ArraysTest.java:18:50:18:54 | ... + ... |
|
||||
| ArraysTest.java:18:54:18:54 | y | ArraysTest.java:18:50:18:54 | ... + ... |
|
||||
| ArraysTest.java:19:38:19:44 | Integer | ArraysTest.java:19:38:19:56 | toString(...) |
|
||||
| ArraysTest.java:19:55:19:55 | x | ArraysTest.java:19:38:19:56 | toString(...) |
|
||||
| ArraysTest.java:20:30:20:36 | Integer | ArraysTest.java:20:30:20:48 | toString(...) |
|
||||
| ArraysTest.java:20:47:20:47 | x | ArraysTest.java:20:30:20:48 | toString(...) |
|
||||
| CollectionsTest.java:10:28:10:32 | "one" | CollectionsTest.java:10:3:10:33 | new ..[] { .. } |
|
||||
| CollectionsTest.java:10:28:10:32 | "one" | CollectionsTest.java:10:22:10:25 | list [post update] |
|
||||
| CollectionsTest.java:11:28:11:32 | "two" | CollectionsTest.java:11:3:11:42 | new ..[] { .. } |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.springframework.ldap.core;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.naming.Name;
|
||||
@@ -9,7 +11,7 @@ import org.springframework.ldap.filter.Filter;
|
||||
|
||||
import org.springframework.ldap.query.LdapQuery;
|
||||
|
||||
public class LdapTemplate {
|
||||
public class LdapTemplate implements LdapOperations, InitializingBean {
|
||||
public void authenticate(LdapQuery query, String password) { }
|
||||
|
||||
public boolean authenticate(Name base, String filter, String password) { return true; }
|
||||
@@ -22,7 +24,53 @@ public class LdapTemplate {
|
||||
|
||||
public void search(String base, String filter, int searchScope, boolean returningObjFlag, NameClassPairCallbackHandler handler) { }
|
||||
|
||||
public void search(final String base, final String filter, final SearchControls controls, NameClassPairCallbackHandler handler) {}
|
||||
|
||||
public void search(final String base, final String filter, final SearchControls controls, NameClassPairCallbackHandler handler, DirContextProcessor processor) {}
|
||||
|
||||
public void search(String base, String filter, NameClassPairCallbackHandler handler) {}
|
||||
|
||||
public <T> List<T> search(String base, String filter, int searchScope, String[] attrs, AttributesMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, int searchScope, AttributesMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, AttributesMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, int searchScope, String[] attrs, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, int searchScope, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, SearchControls controls, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, SearchControls controls, AttributesMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, SearchControls controls, AttributesMapper<T> mapper, DirContextProcessor processor) { return null; }
|
||||
|
||||
public <T> List<T> search(String base, String filter, SearchControls controls, ContextMapper<T> mapper, DirContextProcessor processor) { return null; }
|
||||
|
||||
public DirContextOperations searchForContext(LdapQuery query) { return null; }
|
||||
|
||||
public <T> T searchForObject(Name base, String filter, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> T searchForObject(String base, String filter, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public <T> T searchForObject(String base, String filter, SearchControls searchControls, ContextMapper<T> mapper) { return null; }
|
||||
|
||||
public Object lookup(final String dn) { return new Object(); }
|
||||
|
||||
public DirContextOperations lookupContext(String dn) { return null; }
|
||||
|
||||
public <T> T findByDn(Name dn, final Class<T> clazz) { return null; }
|
||||
|
||||
public void rename(final Name oldDn, final Name newDn) {}
|
||||
|
||||
public List<String> list(final Name base) { return null; }
|
||||
|
||||
public List<String> listBindings(final Name base) { return null; }
|
||||
|
||||
public void unbind(final String dn) {}
|
||||
|
||||
public void unbind(final String dn, boolean recursive) {}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@ import DataFlow::PathGraph
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
|
||||
where cfg.hasFlowPath(source, sink) and sinkNode = sink.getNode()
|
||||
select sinkNode.getAlertLocation(), source, sink, "$@ based on libary input is later used in $@.",
|
||||
select sinkNode.getAlertLocation(), source, sink, "$@ based on library input is later used in $@.",
|
||||
sinkNode.getAlertLocation(), sinkNode.getSinkType(), sinkNode.getCommandExecution(),
|
||||
"shell command"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<img alt="
|
||||
<div alt="
|
||||
<x" title="></x" >
|
||||
<img src=url404 onerror=alert(1)>"/>
|
||||
|
||||
@@ -12,16 +12,16 @@ class Location extends @location {
|
||||
/** Gets the file for this location. */
|
||||
File getFile() { locations_default(this, result, _, _, _, _) }
|
||||
|
||||
/** Gets the start line of this location. */
|
||||
/** Gets the 1-based line number (inclusive) where this location starts. */
|
||||
int getStartLine() { locations_default(this, _, result, _, _, _) }
|
||||
|
||||
/** Gets the start column of this location. */
|
||||
/** Gets the 1-based column number (inclusive) where this location starts. */
|
||||
int getStartColumn() { locations_default(this, _, _, result, _, _) }
|
||||
|
||||
/** Gets the end line of this location. */
|
||||
/** Gets the 1-based line number (inclusive) where this location ends. */
|
||||
int getEndLine() { locations_default(this, _, _, _, result, _) }
|
||||
|
||||
/** Gets the end column of this location. */
|
||||
/** Gets the 1-based column number (inclusive) where this location ends. */
|
||||
int getEndColumn() { locations_default(this, _, _, _, _, result) }
|
||||
|
||||
/** Gets the number of lines covered by this location. */
|
||||
|
||||
@@ -463,6 +463,26 @@ module Express {
|
||||
override RequestSource src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the "query" object from a request-object originating from route-handler `rh`.
|
||||
*/
|
||||
DataFlow::SourceNode getAQueryObjectReference(DataFlow::TypeTracker t, RouteHandler rh) {
|
||||
t.startInProp("query") and
|
||||
result = rh.getARequestSource()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = getAQueryObjectReference(t2, rh).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the "params" object from a request-object originating from route-handler `rh`.
|
||||
*/
|
||||
DataFlow::SourceNode getAParamsObjectReference(DataFlow::TypeTracker t, RouteHandler rh) {
|
||||
t.startInProp("params") and
|
||||
result = rh.getARequestSource()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = getAParamsObjectReference(t2, rh).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* An access to a user-controlled Express request input.
|
||||
*/
|
||||
@@ -471,13 +491,14 @@ module Express {
|
||||
string kind;
|
||||
|
||||
RequestInputAccess() {
|
||||
kind = "parameter" and
|
||||
this =
|
||||
[getAQueryObjectReference(DataFlow::TypeTracker::end(), rh),
|
||||
getAParamsObjectReference(DataFlow::TypeTracker::end(), rh)].getAPropertyRead()
|
||||
or
|
||||
exists(DataFlow::SourceNode request | request = rh.getARequestSource().ref() |
|
||||
kind = "parameter" and
|
||||
(
|
||||
this = request.getAMethodCall("param")
|
||||
or
|
||||
this = request.getAPropertyRead(["params", "query"]).getAPropertyRead()
|
||||
)
|
||||
this = request.getAMethodCall("param")
|
||||
or
|
||||
// `req.originalUrl`
|
||||
kind = "url" and
|
||||
@@ -518,13 +539,11 @@ module Express {
|
||||
kind = "parameter" and
|
||||
exists(DataFlow::Node request | request = DataFlow::valueNode(rh.getARequestExpr()) |
|
||||
this.(DataFlow::MethodCallNode).calls(request, "param")
|
||||
or
|
||||
exists(DataFlow::PropRead base |
|
||||
// `req.query.name`
|
||||
base.accesses(request, "query") and
|
||||
this = base.getAPropertyReference(_)
|
||||
)
|
||||
)
|
||||
or
|
||||
// `req.query.name`
|
||||
kind = "parameter" and
|
||||
this = getAQueryObjectReference(DataFlow::TypeTracker::end(), rh).getAPropertyRead()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,5 +50,9 @@ module ClientSideUrlRedirect {
|
||||
g instanceof DocumentUrl and
|
||||
succ.(DataFlow::PropRead).accesses(pred, "href")
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof HostnameSanitizerGuard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.RemoteFlowSources
|
||||
import UrlConcatenation
|
||||
private import UrlConcatenation
|
||||
|
||||
module ClientSideUrlRedirect {
|
||||
private import Xss::DomBasedXss as DomBasedXss
|
||||
|
||||
@@ -34,7 +34,8 @@ module ServerSideUrlRedirect {
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof LocalUrlSanitizingGuard
|
||||
guard instanceof LocalUrlSanitizingGuard or
|
||||
guard instanceof HostnameSanitizerGuard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import javascript
|
||||
import RemoteFlowSources
|
||||
import UrlConcatenation
|
||||
private import UrlConcatenation
|
||||
|
||||
module ServerSideUrlRedirect {
|
||||
/**
|
||||
|
||||
@@ -96,3 +96,15 @@ predicate hostnameSanitizingPrefixEdge(DataFlow::Node source, DataFlow::Node sin
|
||||
hasHostnameSanitizingSubstring(StringConcatenation::getOperand(operator, [0 .. n - 1]))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A check that sanitizes the hostname of a URL.
|
||||
*/
|
||||
class HostnameSanitizerGuard extends TaintTracking::SanitizerGuardNode, StringOps::StartsWith {
|
||||
HostnameSanitizerGuard() { hasHostnameSanitizingSubstring(getSubstring()) }
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
outcome = getPolarity() and
|
||||
e = getBaseString().asExpr()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,55 +389,55 @@ edges
|
||||
| lib/lib.js:314:40:314:43 | name | lib/lib.js:320:23:320:26 | name |
|
||||
| lib/lib.js:314:40:314:43 | name | lib/lib.js:320:23:320:26 | name |
|
||||
#select
|
||||
| lib/lib2.js:4:10:4:25 | "rm -rf " + name | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | $@ based on libary input is later used in $@. | lib/lib2.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/lib2.js:4:2:4:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib2.js:8:10:8:25 | "rm -rf " + name | lib/lib2.js:7:32:7:35 | name | lib/lib2.js:8:22:8:25 | name | $@ based on libary input is later used in $@. | lib/lib2.js:8:10:8:25 | "rm -rf " + name | String concatenation | lib/lib2.js:8:2:8:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:4:10:4:25 | "rm -rf " + name | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:22:4:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/lib.js:4:2:4:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:11:10:11:25 | "rm -rf " + name | lib/lib.js:10:32:10:35 | name | lib/lib.js:11:22:11:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:11:10:11:25 | "rm -rf " + name | String concatenation | lib/lib.js:11:2:11:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:15:10:15:25 | "rm -rf " + name | lib/lib.js:14:36:14:39 | name | lib/lib.js:15:22:15:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:15:10:15:25 | "rm -rf " + name | String concatenation | lib/lib.js:15:2:15:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:20:10:20:25 | "rm -rf " + name | lib/lib.js:19:34:19:37 | name | lib/lib.js:20:22:20:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:20:10:20:25 | "rm -rf " + name | String concatenation | lib/lib.js:20:2:20:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:27:10:27:25 | "rm -rf " + name | lib/lib.js:26:35:26:38 | name | lib/lib.js:27:22:27:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:27:10:27:25 | "rm -rf " + name | String concatenation | lib/lib.js:27:2:27:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:35:11:35:26 | "rm -rf " + name | lib/lib.js:34:14:34:17 | name | lib/lib.js:35:23:35:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:35:11:35:26 | "rm -rf " + name | String concatenation | lib/lib.js:35:3:35:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:38:11:38:26 | "rm -rf " + name | lib/lib.js:37:13:37:16 | name | lib/lib.js:38:23:38:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:38:11:38:26 | "rm -rf " + name | String concatenation | lib/lib.js:38:3:38:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:41:11:41:26 | "rm -rf " + name | lib/lib.js:40:6:40:9 | name | lib/lib.js:41:23:41:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:41:11:41:26 | "rm -rf " + name | String concatenation | lib/lib.js:41:3:41:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:50:35:50:50 | "rm -rf " + name | lib/lib.js:49:31:49:34 | name | lib/lib.js:50:47:50:50 | name | $@ based on libary input is later used in $@. | lib/lib.js:50:35:50:50 | "rm -rf " + name | String concatenation | lib/lib.js:50:2:50:51 | require ... + name) | shell command |
|
||||
| lib/lib.js:54:13:54:28 | "rm -rf " + name | lib/lib.js:53:33:53:36 | name | lib/lib.js:54:25:54:28 | name | $@ based on libary input is later used in $@. | lib/lib.js:54:13:54:28 | "rm -rf " + name | String concatenation | lib/lib.js:55:2:55:14 | cp.exec(cmd1) | shell command |
|
||||
| lib/lib.js:57:13:57:28 | "rm -rf " + name | lib/lib.js:53:33:53:36 | name | lib/lib.js:57:25:57:28 | name | $@ based on libary input is later used in $@. | lib/lib.js:57:13:57:28 | "rm -rf " + name | String concatenation | lib/lib.js:59:3:59:14 | cp.exec(cmd) | shell command |
|
||||
| lib/lib.js:65:10:65:25 | "rm -rf " + name | lib/lib.js:64:41:64:44 | name | lib/lib.js:65:22:65:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:65:10:65:25 | "rm -rf " + name | String concatenation | lib/lib.js:65:2:65:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:71:10:71:31 | "cat /f ... + name | lib/lib.js:64:41:64:44 | name | lib/lib.js:71:28:71:31 | name | $@ based on libary input is later used in $@. | lib/lib.js:71:10:71:31 | "cat /f ... + name | String concatenation | lib/lib.js:71:2:71:32 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:73:10:73:31 | "cat \\" ... + "\\"" | lib/lib.js:64:41:64:44 | name | lib/lib.js:73:21:73:24 | name | $@ based on libary input is later used in $@. | lib/lib.js:73:10:73:31 | "cat \\" ... + "\\"" | String concatenation | lib/lib.js:73:2:73:32 | cp.exec ... + "\\"") | shell command |
|
||||
| lib/lib.js:75:10:75:29 | "cat '" + name + "'" | lib/lib.js:64:41:64:44 | name | lib/lib.js:75:20:75:23 | name | $@ based on libary input is later used in $@. | lib/lib.js:75:10:75:29 | "cat '" + name + "'" | String concatenation | lib/lib.js:75:2:75:30 | cp.exec ... + "'") | shell command |
|
||||
| lib/lib.js:77:10:77:37 | "cat '/ ... e + "'" | lib/lib.js:64:41:64:44 | name | lib/lib.js:77:28:77:31 | name | $@ based on libary input is later used in $@. | lib/lib.js:77:10:77:37 | "cat '/ ... e + "'" | String concatenation | lib/lib.js:77:2:77:38 | cp.exec ... + "'") | shell command |
|
||||
| lib/lib.js:83:10:83:25 | "rm -rf " + name | lib/lib.js:82:35:82:38 | name | lib/lib.js:83:22:83:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:83:10:83:25 | "rm -rf " + name | String concatenation | lib/lib.js:83:2:83:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:86:13:86:16 | name | lib/lib.js:82:35:82:38 | name | lib/lib.js:86:13:86:16 | name | $@ based on libary input is later used in $@. | lib/lib.js:86:13:86:16 | name | Array element | lib/lib.js:87:2:87:25 | cp.exec ... n(" ")) | shell command |
|
||||
| lib/lib.js:89:21:89:24 | name | lib/lib.js:82:35:82:38 | name | lib/lib.js:89:21:89:24 | name | $@ based on libary input is later used in $@. | lib/lib.js:89:21:89:24 | name | Array element | lib/lib.js:89:2:89:36 | cp.exec ... n(" ")) | shell command |
|
||||
| lib/lib.js:91:21:91:38 | "\\"" + name + "\\"" | lib/lib.js:82:35:82:38 | name | lib/lib.js:91:21:91:38 | "\\"" + name + "\\"" | $@ based on libary input is later used in $@. | lib/lib.js:91:21:91:38 | "\\"" + name + "\\"" | Array element | lib/lib.js:91:2:91:50 | cp.exec ... n(" ")) | shell command |
|
||||
| lib/lib.js:98:35:98:38 | name | lib/lib.js:97:35:97:38 | name | lib/lib.js:98:35:98:38 | name | $@ based on libary input is later used in $@. | lib/lib.js:98:35:98:38 | name | Formatted string | lib/lib.js:98:2:98:40 | cp.exec ... name)) | shell command |
|
||||
| lib/lib.js:100:37:100:40 | name | lib/lib.js:97:35:97:38 | name | lib/lib.js:100:37:100:40 | name | $@ based on libary input is later used in $@. | lib/lib.js:100:37:100:40 | name | Formatted string | lib/lib.js:100:2:100:42 | cp.exec ... name)) | shell command |
|
||||
| lib/lib.js:102:46:102:49 | name | lib/lib.js:97:35:97:38 | name | lib/lib.js:102:46:102:49 | name | $@ based on libary input is later used in $@. | lib/lib.js:102:46:102:49 | name | Formatted string | lib/lib.js:102:2:102:51 | cp.exec ... name)) | shell command |
|
||||
| lib/lib.js:108:41:108:44 | name | lib/lib.js:97:35:97:38 | name | lib/lib.js:108:41:108:44 | name | $@ based on libary input is later used in $@. | lib/lib.js:108:41:108:44 | name | Formatted string | lib/lib.js:108:2:108:46 | cp.exec ... name)) | shell command |
|
||||
| lib/lib.js:112:10:112:25 | "rm -rf " + name | lib/lib.js:111:34:111:37 | name | lib/lib.js:112:22:112:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:112:10:112:25 | "rm -rf " + name | String concatenation | lib/lib.js:112:2:112:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:121:10:121:25 | "rm -rf " + name | lib/lib.js:120:33:120:36 | name | lib/lib.js:121:22:121:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:121:10:121:25 | "rm -rf " + name | String concatenation | lib/lib.js:121:2:121:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:131:11:131:26 | "rm -rf " + name | lib/lib.js:130:6:130:9 | name | lib/lib.js:131:23:131:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:131:11:131:26 | "rm -rf " + name | String concatenation | lib/lib.js:131:3:131:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:149:12:149:27 | "rm -rf " + name | lib/lib.js:148:37:148:40 | name | lib/lib.js:149:24:149:27 | name | $@ based on libary input is later used in $@. | lib/lib.js:149:12:149:27 | "rm -rf " + name | String concatenation | lib/lib.js:152:2:152:23 | cp.spaw ... gs, cb) | shell command |
|
||||
| lib/lib.js:161:13:161:28 | "rm -rf " + name | lib/lib.js:155:38:155:41 | name | lib/lib.js:161:25:161:28 | name | $@ based on libary input is later used in $@. | lib/lib.js:161:13:161:28 | "rm -rf " + name | String concatenation | lib/lib.js:163:2:167:2 | cp.spaw ... t' }\\n\\t) | shell command |
|
||||
| lib/lib.js:173:10:173:23 | "fo \| " + name | lib/lib.js:170:41:170:44 | name | lib/lib.js:173:20:173:23 | name | $@ based on libary input is later used in $@. | lib/lib.js:173:10:173:23 | "fo \| " + name | String concatenation | lib/lib.js:173:2:173:24 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:182:10:182:27 | "rm -rf " + broken | lib/lib.js:177:38:177:41 | name | lib/lib.js:182:22:182:27 | broken | $@ based on libary input is later used in $@. | lib/lib.js:182:10:182:27 | "rm -rf " + broken | String concatenation | lib/lib.js:182:2:182:28 | cp.exec ... broken) | shell command |
|
||||
| lib/lib.js:187:10:187:25 | "rm -rf " + name | lib/lib.js:186:34:186:37 | name | lib/lib.js:187:22:187:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:187:10:187:25 | "rm -rf " + name | String concatenation | lib/lib.js:187:2:187:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:190:11:190:26 | "rm -rf " + name | lib/lib.js:186:34:186:37 | name | lib/lib.js:190:23:190:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:190:11:190:26 | "rm -rf " + name | String concatenation | lib/lib.js:190:3:190:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:197:10:197:25 | "rm -rf " + name | lib/lib.js:196:45:196:48 | name | lib/lib.js:197:22:197:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:197:10:197:25 | "rm -rf " + name | String concatenation | lib/lib.js:197:2:197:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:200:11:200:26 | "rm -rf " + name | lib/lib.js:196:45:196:48 | name | lib/lib.js:200:23:200:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:200:11:200:26 | "rm -rf " + name | String concatenation | lib/lib.js:200:3:200:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:207:10:207:25 | "rm -rf " + name | lib/lib.js:206:45:206:48 | name | lib/lib.js:207:22:207:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:207:10:207:25 | "rm -rf " + name | String concatenation | lib/lib.js:207:2:207:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:212:11:212:26 | "rm -rf " + name | lib/lib.js:206:45:206:48 | name | lib/lib.js:212:23:212:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:212:11:212:26 | "rm -rf " + name | String concatenation | lib/lib.js:212:3:212:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:217:10:217:25 | "rm -rf " + name | lib/lib.js:216:39:216:42 | name | lib/lib.js:217:22:217:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:217:10:217:25 | "rm -rf " + name | String concatenation | lib/lib.js:217:2:217:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:220:11:220:26 | "rm -rf " + name | lib/lib.js:216:39:216:42 | name | lib/lib.js:220:23:220:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:220:11:220:26 | "rm -rf " + name | String concatenation | lib/lib.js:220:3:220:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:224:10:224:25 | "rm -rf " + name | lib/lib.js:216:39:216:42 | name | lib/lib.js:224:22:224:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:224:10:224:25 | "rm -rf " + name | String concatenation | lib/lib.js:224:2:224:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:228:10:228:25 | "rm -rf " + name | lib/lib.js:227:39:227:42 | name | lib/lib.js:228:22:228:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:228:10:228:25 | "rm -rf " + name | String concatenation | lib/lib.js:228:2:228:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:236:10:236:25 | "rm -rf " + name | lib/lib.js:227:39:227:42 | name | lib/lib.js:236:22:236:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:236:10:236:25 | "rm -rf " + name | String concatenation | lib/lib.js:236:2:236:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:249:10:249:25 | "rm -rf " + name | lib/lib.js:248:42:248:45 | name | lib/lib.js:249:22:249:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:249:10:249:25 | "rm -rf " + name | String concatenation | lib/lib.js:249:2:249:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:258:10:258:25 | "rm -rf " + name | lib/lib.js:257:35:257:38 | name | lib/lib.js:258:22:258:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:258:10:258:25 | "rm -rf " + name | String concatenation | lib/lib.js:258:2:258:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:261:11:261:33 | "rm -rf ... + name | lib/lib.js:257:35:257:38 | name | lib/lib.js:261:30:261:33 | name | $@ based on libary input is later used in $@. | lib/lib.js:261:11:261:33 | "rm -rf ... + name | String concatenation | lib/lib.js:261:3:261:34 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:268:10:268:32 | "rm -rf ... version | lib/lib.js:267:46:267:48 | obj | lib/lib.js:268:22:268:32 | obj.version | $@ based on libary input is later used in $@. | lib/lib.js:268:10:268:32 | "rm -rf ... version | String concatenation | lib/lib.js:268:2:268:33 | cp.exec ... ersion) | shell command |
|
||||
| lib/lib.js:277:11:277:30 | "rm -rf " + opts.bla | lib/lib.js:276:8:276:11 | opts | lib/lib.js:277:23:277:30 | opts.bla | $@ based on libary input is later used in $@. | lib/lib.js:277:11:277:30 | "rm -rf " + opts.bla | String concatenation | lib/lib.js:277:3:277:31 | cp.exec ... ts.bla) | shell command |
|
||||
| lib/lib.js:308:11:308:26 | "rm -rf " + name | lib/lib.js:307:39:307:42 | name | lib/lib.js:308:23:308:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:308:11:308:26 | "rm -rf " + name | String concatenation | lib/lib.js:308:3:308:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:315:10:315:25 | "rm -rf " + name | lib/lib.js:314:40:314:43 | name | lib/lib.js:315:22:315:25 | name | $@ based on libary input is later used in $@. | lib/lib.js:315:10:315:25 | "rm -rf " + name | String concatenation | lib/lib.js:315:2:315:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:320:11:320:26 | "rm -rf " + name | lib/lib.js:314:40:314:43 | name | lib/lib.js:320:23:320:26 | name | $@ based on libary input is later used in $@. | lib/lib.js:320:11:320:26 | "rm -rf " + name | String concatenation | lib/lib.js:320:3:320:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib2.js:4:10:4:25 | "rm -rf " + name | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/lib2.js:4:2:4:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib2.js:8:10:8:25 | "rm -rf " + name | lib/lib2.js:7:32:7:35 | name | lib/lib2.js:8:22:8:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:8:10:8:25 | "rm -rf " + name | String concatenation | lib/lib2.js:8:2:8:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:4:10:4:25 | "rm -rf " + name | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:22:4:25 | name | $@ based on library input is later used in $@. | lib/lib.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/lib.js:4:2:4:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:11:10:11:25 | "rm -rf " + name | lib/lib.js:10:32:10:35 | name | lib/lib.js:11:22:11:25 | name | $@ based on library input is later used in $@. | lib/lib.js:11:10:11:25 | "rm -rf " + name | String concatenation | lib/lib.js:11:2:11:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:15:10:15:25 | "rm -rf " + name | lib/lib.js:14:36:14:39 | name | lib/lib.js:15:22:15:25 | name | $@ based on library input is later used in $@. | lib/lib.js:15:10:15:25 | "rm -rf " + name | String concatenation | lib/lib.js:15:2:15:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:20:10:20:25 | "rm -rf " + name | lib/lib.js:19:34:19:37 | name | lib/lib.js:20:22:20:25 | name | $@ based on library input is later used in $@. | lib/lib.js:20:10:20:25 | "rm -rf " + name | String concatenation | lib/lib.js:20:2:20:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:27:10:27:25 | "rm -rf " + name | lib/lib.js:26:35:26:38 | name | lib/lib.js:27:22:27:25 | name | $@ based on library input is later used in $@. | lib/lib.js:27:10:27:25 | "rm -rf " + name | String concatenation | lib/lib.js:27:2:27:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:35:11:35:26 | "rm -rf " + name | lib/lib.js:34:14:34:17 | name | lib/lib.js:35:23:35:26 | name | $@ based on library input is later used in $@. | lib/lib.js:35:11:35:26 | "rm -rf " + name | String concatenation | lib/lib.js:35:3:35:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:38:11:38:26 | "rm -rf " + name | lib/lib.js:37:13:37:16 | name | lib/lib.js:38:23:38:26 | name | $@ based on library input is later used in $@. | lib/lib.js:38:11:38:26 | "rm -rf " + name | String concatenation | lib/lib.js:38:3:38:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:41:11:41:26 | "rm -rf " + name | lib/lib.js:40:6:40:9 | name | lib/lib.js:41:23:41:26 | name | $@ based on library input is later used in $@. | lib/lib.js:41:11:41:26 | "rm -rf " + name | String concatenation | lib/lib.js:41:3:41:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:50:35:50:50 | "rm -rf " + name | lib/lib.js:49:31:49:34 | name | lib/lib.js:50:47:50:50 | name | $@ based on library input is later used in $@. | lib/lib.js:50:35:50:50 | "rm -rf " + name | String concatenation | lib/lib.js:50:2:50:51 | require ... + name) | shell command |
|
||||
| lib/lib.js:54:13:54:28 | "rm -rf " + name | lib/lib.js:53:33:53:36 | name | lib/lib.js:54:25:54:28 | name | $@ based on library input is later used in $@. | lib/lib.js:54:13:54:28 | "rm -rf " + name | String concatenation | lib/lib.js:55:2:55:14 | cp.exec(cmd1) | shell command |
|
||||
| lib/lib.js:57:13:57:28 | "rm -rf " + name | lib/lib.js:53:33:53:36 | name | lib/lib.js:57:25:57:28 | name | $@ based on library input is later used in $@. | lib/lib.js:57:13:57:28 | "rm -rf " + name | String concatenation | lib/lib.js:59:3:59:14 | cp.exec(cmd) | shell command |
|
||||
| lib/lib.js:65:10:65:25 | "rm -rf " + name | lib/lib.js:64:41:64:44 | name | lib/lib.js:65:22:65:25 | name | $@ based on library input is later used in $@. | lib/lib.js:65:10:65:25 | "rm -rf " + name | String concatenation | lib/lib.js:65:2:65:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:71:10:71:31 | "cat /f ... + name | lib/lib.js:64:41:64:44 | name | lib/lib.js:71:28:71:31 | name | $@ based on library input is later used in $@. | lib/lib.js:71:10:71:31 | "cat /f ... + name | String concatenation | lib/lib.js:71:2:71:32 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:73:10:73:31 | "cat \\" ... + "\\"" | lib/lib.js:64:41:64:44 | name | lib/lib.js:73:21:73:24 | name | $@ based on library input is later used in $@. | lib/lib.js:73:10:73:31 | "cat \\" ... + "\\"" | String concatenation | lib/lib.js:73:2:73:32 | cp.exec ... + "\\"") | shell command |
|
||||
| lib/lib.js:75:10:75:29 | "cat '" + name + "'" | lib/lib.js:64:41:64:44 | name | lib/lib.js:75:20:75:23 | name | $@ based on library input is later used in $@. | lib/lib.js:75:10:75:29 | "cat '" + name + "'" | String concatenation | lib/lib.js:75:2:75:30 | cp.exec ... + "'") | shell command |
|
||||
| lib/lib.js:77:10:77:37 | "cat '/ ... e + "'" | lib/lib.js:64:41:64:44 | name | lib/lib.js:77:28:77:31 | name | $@ based on library input is later used in $@. | lib/lib.js:77:10:77:37 | "cat '/ ... e + "'" | String concatenation | lib/lib.js:77:2:77:38 | cp.exec ... + "'") | shell command |
|
||||
| lib/lib.js:83:10:83:25 | "rm -rf " + name | lib/lib.js:82:35:82:38 | name | lib/lib.js:83:22:83:25 | name | $@ based on library input is later used in $@. | lib/lib.js:83:10:83:25 | "rm -rf " + name | String concatenation | lib/lib.js:83:2:83:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:86:13:86:16 | name | lib/lib.js:82:35:82:38 | name | lib/lib.js:86:13:86:16 | name | $@ based on library input is later used in $@. | lib/lib.js:86:13:86:16 | name | Array element | lib/lib.js:87:2:87:25 | cp.exec ... n(" ")) | shell command |
|
||||
| lib/lib.js:89:21:89:24 | name | lib/lib.js:82:35:82:38 | name | lib/lib.js:89:21:89:24 | name | $@ based on library input is later used in $@. | lib/lib.js:89:21:89:24 | name | Array element | lib/lib.js:89:2:89:36 | cp.exec ... n(" ")) | shell command |
|
||||
| lib/lib.js:91:21:91:38 | "\\"" + name + "\\"" | lib/lib.js:82:35:82:38 | name | lib/lib.js:91:21:91:38 | "\\"" + name + "\\"" | $@ based on library input is later used in $@. | lib/lib.js:91:21:91:38 | "\\"" + name + "\\"" | Array element | lib/lib.js:91:2:91:50 | cp.exec ... n(" ")) | shell command |
|
||||
| lib/lib.js:98:35:98:38 | name | lib/lib.js:97:35:97:38 | name | lib/lib.js:98:35:98:38 | name | $@ based on library input is later used in $@. | lib/lib.js:98:35:98:38 | name | Formatted string | lib/lib.js:98:2:98:40 | cp.exec ... name)) | shell command |
|
||||
| lib/lib.js:100:37:100:40 | name | lib/lib.js:97:35:97:38 | name | lib/lib.js:100:37:100:40 | name | $@ based on library input is later used in $@. | lib/lib.js:100:37:100:40 | name | Formatted string | lib/lib.js:100:2:100:42 | cp.exec ... name)) | shell command |
|
||||
| lib/lib.js:102:46:102:49 | name | lib/lib.js:97:35:97:38 | name | lib/lib.js:102:46:102:49 | name | $@ based on library input is later used in $@. | lib/lib.js:102:46:102:49 | name | Formatted string | lib/lib.js:102:2:102:51 | cp.exec ... name)) | shell command |
|
||||
| lib/lib.js:108:41:108:44 | name | lib/lib.js:97:35:97:38 | name | lib/lib.js:108:41:108:44 | name | $@ based on library input is later used in $@. | lib/lib.js:108:41:108:44 | name | Formatted string | lib/lib.js:108:2:108:46 | cp.exec ... name)) | shell command |
|
||||
| lib/lib.js:112:10:112:25 | "rm -rf " + name | lib/lib.js:111:34:111:37 | name | lib/lib.js:112:22:112:25 | name | $@ based on library input is later used in $@. | lib/lib.js:112:10:112:25 | "rm -rf " + name | String concatenation | lib/lib.js:112:2:112:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:121:10:121:25 | "rm -rf " + name | lib/lib.js:120:33:120:36 | name | lib/lib.js:121:22:121:25 | name | $@ based on library input is later used in $@. | lib/lib.js:121:10:121:25 | "rm -rf " + name | String concatenation | lib/lib.js:121:2:121:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:131:11:131:26 | "rm -rf " + name | lib/lib.js:130:6:130:9 | name | lib/lib.js:131:23:131:26 | name | $@ based on library input is later used in $@. | lib/lib.js:131:11:131:26 | "rm -rf " + name | String concatenation | lib/lib.js:131:3:131:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:149:12:149:27 | "rm -rf " + name | lib/lib.js:148:37:148:40 | name | lib/lib.js:149:24:149:27 | name | $@ based on library input is later used in $@. | lib/lib.js:149:12:149:27 | "rm -rf " + name | String concatenation | lib/lib.js:152:2:152:23 | cp.spaw ... gs, cb) | shell command |
|
||||
| lib/lib.js:161:13:161:28 | "rm -rf " + name | lib/lib.js:155:38:155:41 | name | lib/lib.js:161:25:161:28 | name | $@ based on library input is later used in $@. | lib/lib.js:161:13:161:28 | "rm -rf " + name | String concatenation | lib/lib.js:163:2:167:2 | cp.spaw ... t' }\\n\\t) | shell command |
|
||||
| lib/lib.js:173:10:173:23 | "fo \| " + name | lib/lib.js:170:41:170:44 | name | lib/lib.js:173:20:173:23 | name | $@ based on library input is later used in $@. | lib/lib.js:173:10:173:23 | "fo \| " + name | String concatenation | lib/lib.js:173:2:173:24 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:182:10:182:27 | "rm -rf " + broken | lib/lib.js:177:38:177:41 | name | lib/lib.js:182:22:182:27 | broken | $@ based on library input is later used in $@. | lib/lib.js:182:10:182:27 | "rm -rf " + broken | String concatenation | lib/lib.js:182:2:182:28 | cp.exec ... broken) | shell command |
|
||||
| lib/lib.js:187:10:187:25 | "rm -rf " + name | lib/lib.js:186:34:186:37 | name | lib/lib.js:187:22:187:25 | name | $@ based on library input is later used in $@. | lib/lib.js:187:10:187:25 | "rm -rf " + name | String concatenation | lib/lib.js:187:2:187:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:190:11:190:26 | "rm -rf " + name | lib/lib.js:186:34:186:37 | name | lib/lib.js:190:23:190:26 | name | $@ based on library input is later used in $@. | lib/lib.js:190:11:190:26 | "rm -rf " + name | String concatenation | lib/lib.js:190:3:190:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:197:10:197:25 | "rm -rf " + name | lib/lib.js:196:45:196:48 | name | lib/lib.js:197:22:197:25 | name | $@ based on library input is later used in $@. | lib/lib.js:197:10:197:25 | "rm -rf " + name | String concatenation | lib/lib.js:197:2:197:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:200:11:200:26 | "rm -rf " + name | lib/lib.js:196:45:196:48 | name | lib/lib.js:200:23:200:26 | name | $@ based on library input is later used in $@. | lib/lib.js:200:11:200:26 | "rm -rf " + name | String concatenation | lib/lib.js:200:3:200:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:207:10:207:25 | "rm -rf " + name | lib/lib.js:206:45:206:48 | name | lib/lib.js:207:22:207:25 | name | $@ based on library input is later used in $@. | lib/lib.js:207:10:207:25 | "rm -rf " + name | String concatenation | lib/lib.js:207:2:207:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:212:11:212:26 | "rm -rf " + name | lib/lib.js:206:45:206:48 | name | lib/lib.js:212:23:212:26 | name | $@ based on library input is later used in $@. | lib/lib.js:212:11:212:26 | "rm -rf " + name | String concatenation | lib/lib.js:212:3:212:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:217:10:217:25 | "rm -rf " + name | lib/lib.js:216:39:216:42 | name | lib/lib.js:217:22:217:25 | name | $@ based on library input is later used in $@. | lib/lib.js:217:10:217:25 | "rm -rf " + name | String concatenation | lib/lib.js:217:2:217:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:220:11:220:26 | "rm -rf " + name | lib/lib.js:216:39:216:42 | name | lib/lib.js:220:23:220:26 | name | $@ based on library input is later used in $@. | lib/lib.js:220:11:220:26 | "rm -rf " + name | String concatenation | lib/lib.js:220:3:220:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:224:10:224:25 | "rm -rf " + name | lib/lib.js:216:39:216:42 | name | lib/lib.js:224:22:224:25 | name | $@ based on library input is later used in $@. | lib/lib.js:224:10:224:25 | "rm -rf " + name | String concatenation | lib/lib.js:224:2:224:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:228:10:228:25 | "rm -rf " + name | lib/lib.js:227:39:227:42 | name | lib/lib.js:228:22:228:25 | name | $@ based on library input is later used in $@. | lib/lib.js:228:10:228:25 | "rm -rf " + name | String concatenation | lib/lib.js:228:2:228:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:236:10:236:25 | "rm -rf " + name | lib/lib.js:227:39:227:42 | name | lib/lib.js:236:22:236:25 | name | $@ based on library input is later used in $@. | lib/lib.js:236:10:236:25 | "rm -rf " + name | String concatenation | lib/lib.js:236:2:236:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:249:10:249:25 | "rm -rf " + name | lib/lib.js:248:42:248:45 | name | lib/lib.js:249:22:249:25 | name | $@ based on library input is later used in $@. | lib/lib.js:249:10:249:25 | "rm -rf " + name | String concatenation | lib/lib.js:249:2:249:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:258:10:258:25 | "rm -rf " + name | lib/lib.js:257:35:257:38 | name | lib/lib.js:258:22:258:25 | name | $@ based on library input is later used in $@. | lib/lib.js:258:10:258:25 | "rm -rf " + name | String concatenation | lib/lib.js:258:2:258:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:261:11:261:33 | "rm -rf ... + name | lib/lib.js:257:35:257:38 | name | lib/lib.js:261:30:261:33 | name | $@ based on library input is later used in $@. | lib/lib.js:261:11:261:33 | "rm -rf ... + name | String concatenation | lib/lib.js:261:3:261:34 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:268:10:268:32 | "rm -rf ... version | lib/lib.js:267:46:267:48 | obj | lib/lib.js:268:22:268:32 | obj.version | $@ based on library input is later used in $@. | lib/lib.js:268:10:268:32 | "rm -rf ... version | String concatenation | lib/lib.js:268:2:268:33 | cp.exec ... ersion) | shell command |
|
||||
| lib/lib.js:277:11:277:30 | "rm -rf " + opts.bla | lib/lib.js:276:8:276:11 | opts | lib/lib.js:277:23:277:30 | opts.bla | $@ based on library input is later used in $@. | lib/lib.js:277:11:277:30 | "rm -rf " + opts.bla | String concatenation | lib/lib.js:277:3:277:31 | cp.exec ... ts.bla) | shell command |
|
||||
| lib/lib.js:308:11:308:26 | "rm -rf " + name | lib/lib.js:307:39:307:42 | name | lib/lib.js:308:23:308:26 | name | $@ based on library input is later used in $@. | lib/lib.js:308:11:308:26 | "rm -rf " + name | String concatenation | lib/lib.js:308:3:308:27 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:315:10:315:25 | "rm -rf " + name | lib/lib.js:314:40:314:43 | name | lib/lib.js:315:22:315:25 | name | $@ based on library input is later used in $@. | lib/lib.js:315:10:315:25 | "rm -rf " + name | String concatenation | lib/lib.js:315:2:315:26 | cp.exec ... + name) | shell command |
|
||||
| lib/lib.js:320:11:320:26 | "rm -rf " + name | lib/lib.js:314:40:314:43 | name | lib/lib.js:320:23:320:26 | name | $@ based on library input is later used in $@. | lib/lib.js:320:11:320:26 | "rm -rf " + name | String concatenation | lib/lib.js:320:3:320:27 | cp.exec ... + name) | shell command |
|
||||
|
||||
@@ -3,6 +3,10 @@ nodes
|
||||
| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
|
||||
| ReflectedXss.js:8:33:8:45 | req.params.id |
|
||||
| ReflectedXss.js:8:33:8:45 | req.params.id |
|
||||
| ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id |
|
||||
| ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id |
|
||||
| ReflectedXss.js:17:31:17:39 | params.id |
|
||||
| ReflectedXss.js:17:31:17:39 | params.id |
|
||||
| ReflectedXssContentTypes.js:10:14:10:36 | "FOO: " ... rams.id |
|
||||
| ReflectedXssContentTypes.js:10:14:10:36 | "FOO: " ... rams.id |
|
||||
| ReflectedXssContentTypes.js:10:24:10:36 | req.params.id |
|
||||
@@ -95,6 +99,10 @@ edges
|
||||
| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
|
||||
| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
|
||||
| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
|
||||
| ReflectedXss.js:17:31:17:39 | params.id | ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id |
|
||||
| ReflectedXss.js:17:31:17:39 | params.id | ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id |
|
||||
| ReflectedXss.js:17:31:17:39 | params.id | ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id |
|
||||
| ReflectedXss.js:17:31:17:39 | params.id | ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id |
|
||||
| ReflectedXssContentTypes.js:10:24:10:36 | req.params.id | ReflectedXssContentTypes.js:10:14:10:36 | "FOO: " ... rams.id |
|
||||
| ReflectedXssContentTypes.js:10:24:10:36 | req.params.id | ReflectedXssContentTypes.js:10:14:10:36 | "FOO: " ... rams.id |
|
||||
| ReflectedXssContentTypes.js:10:24:10:36 | req.params.id | ReflectedXssContentTypes.js:10:14:10:36 | "FOO: " ... rams.id |
|
||||
@@ -173,6 +181,7 @@ edges
|
||||
| tst2.js:14:9:14:9 | p | tst2.js:14:7:14:24 | p |
|
||||
#select
|
||||
| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:8:33:8:45 | req.params.id | user-provided value |
|
||||
| ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id | ReflectedXss.js:17:31:17:39 | params.id | ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:17:31:17:39 | params.id | user-provided value |
|
||||
| ReflectedXssContentTypes.js:10:14:10:36 | "FOO: " ... rams.id | ReflectedXssContentTypes.js:10:24:10:36 | req.params.id | ReflectedXssContentTypes.js:10:14:10:36 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:10:24:10:36 | req.params.id | user-provided value |
|
||||
| ReflectedXssContentTypes.js:20:14:20:36 | "FOO: " ... rams.id | ReflectedXssContentTypes.js:20:24:20:36 | req.params.id | ReflectedXssContentTypes.js:20:14:20:36 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:20:24:20:36 | req.params.id | user-provided value |
|
||||
| ReflectedXssContentTypes.js:39:13:39:35 | "FOO: " ... rams.id | ReflectedXssContentTypes.js:39:23:39:35 | req.params.id | ReflectedXssContentTypes.js:39:13:39:35 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:39:23:39:35 | req.params.id | user-provided value |
|
||||
|
||||
@@ -3,10 +3,16 @@ var express = require('express');
|
||||
var app = express();
|
||||
|
||||
app.get('/user/:id', function(req, res) {
|
||||
if (!isValidUserId(req.params.id))
|
||||
if (!isValidUserId(req.params.id)) {
|
||||
// BAD: a request parameter is incorporated without validation into the response
|
||||
res.send("Unknown user: " + req.params.id);
|
||||
else
|
||||
moreBadStuff(req.params, res);
|
||||
} else {
|
||||
// TODO: do something exciting
|
||||
;
|
||||
}
|
||||
});
|
||||
|
||||
function moreBadStuff(params, res) {
|
||||
res.send("Unknown user: " + params.id); // NOT OK
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:8:33:8:45 | req.params.id | user-provided value |
|
||||
| ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:17:31:17:39 | params.id | user-provided value |
|
||||
| ReflectedXssContentTypes.js:10:14:10:36 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:10:24:10:36 | req.params.id | user-provided value |
|
||||
| ReflectedXssContentTypes.js:20:14:20:36 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:20:24:20:36 | req.params.id | user-provided value |
|
||||
| ReflectedXssContentTypes.js:39:13:39:35 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:39:23:39:35 | req.params.id | user-provided value |
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
| mongodb.js:65:3:65:17 | doc.find(query) |
|
||||
| mongodb.js:73:5:77:27 | client\\n ... tag }) |
|
||||
| mongodb.js:81:3:85:25 | importe ... tag }) |
|
||||
| mongodb.js:98:5:98:19 | doc.find(query) |
|
||||
| mongodb.js:112:5:112:19 | doc.find(query) |
|
||||
| mongodb_bodySafe.js:18:7:18:21 | doc.find(query) |
|
||||
| mongodb_bodySafe.js:29:7:29:21 | doc.find(query) |
|
||||
| mongoose.js:63:2:63:34 | Documen ... then(X) |
|
||||
|
||||
@@ -56,6 +56,12 @@ nodes
|
||||
| mongodb.js:85:12:85:24 | { tags: tag } |
|
||||
| mongodb.js:85:12:85:24 | { tags: tag } |
|
||||
| mongodb.js:85:20:85:22 | tag |
|
||||
| mongodb.js:106:9:106:18 | query |
|
||||
| mongodb.js:106:17:106:18 | {} |
|
||||
| mongodb.js:107:17:107:29 | queries.title |
|
||||
| mongodb.js:107:17:107:29 | queries.title |
|
||||
| mongodb.js:112:14:112:18 | query |
|
||||
| mongodb.js:112:14:112:18 | query |
|
||||
| mongodb_bodySafe.js:23:11:23:20 | query |
|
||||
| mongodb_bodySafe.js:23:19:23:20 | {} |
|
||||
| mongodb_bodySafe.js:24:19:24:33 | req.query.title |
|
||||
@@ -244,6 +250,17 @@ edges
|
||||
| mongodb.js:77:22:77:24 | tag | mongodb.js:77:14:77:26 | { tags: tag } |
|
||||
| mongodb.js:85:20:85:22 | tag | mongodb.js:85:12:85:24 | { tags: tag } |
|
||||
| mongodb.js:85:20:85:22 | tag | mongodb.js:85:12:85:24 | { tags: tag } |
|
||||
| mongodb.js:106:9:106:18 | query | mongodb.js:112:14:112:18 | query |
|
||||
| mongodb.js:106:9:106:18 | query | mongodb.js:112:14:112:18 | query |
|
||||
| mongodb.js:106:17:106:18 | {} | mongodb.js:106:9:106:18 | query |
|
||||
| mongodb.js:107:17:107:29 | queries.title | mongodb.js:106:9:106:18 | query |
|
||||
| mongodb.js:107:17:107:29 | queries.title | mongodb.js:106:9:106:18 | query |
|
||||
| mongodb.js:107:17:107:29 | queries.title | mongodb.js:106:17:106:18 | {} |
|
||||
| mongodb.js:107:17:107:29 | queries.title | mongodb.js:106:17:106:18 | {} |
|
||||
| mongodb.js:107:17:107:29 | queries.title | mongodb.js:112:14:112:18 | query |
|
||||
| mongodb.js:107:17:107:29 | queries.title | mongodb.js:112:14:112:18 | query |
|
||||
| mongodb.js:107:17:107:29 | queries.title | mongodb.js:112:14:112:18 | query |
|
||||
| mongodb.js:107:17:107:29 | queries.title | mongodb.js:112:14:112:18 | query |
|
||||
| mongodb_bodySafe.js:23:11:23:20 | query | mongodb_bodySafe.js:29:16:29:20 | query |
|
||||
| mongodb_bodySafe.js:23:11:23:20 | query | mongodb_bodySafe.js:29:16:29:20 | query |
|
||||
| mongodb_bodySafe.js:23:19:23:20 | {} | mongodb_bodySafe.js:23:11:23:20 | query |
|
||||
@@ -428,6 +445,7 @@ edges
|
||||
| mongodb.js:65:12:65:16 | query | mongodb.js:60:16:60:30 | req.query.title | mongodb.js:65:12:65:16 | query | This query depends on $@. | mongodb.js:60:16:60:30 | req.query.title | a user-provided value |
|
||||
| mongodb.js:77:14:77:26 | { tags: tag } | mongodb.js:70:13:70:25 | req.query.tag | mongodb.js:77:14:77:26 | { tags: tag } | This query depends on $@. | mongodb.js:70:13:70:25 | req.query.tag | a user-provided value |
|
||||
| mongodb.js:85:12:85:24 | { tags: tag } | mongodb.js:70:13:70:25 | req.query.tag | mongodb.js:85:12:85:24 | { tags: tag } | This query depends on $@. | mongodb.js:70:13:70:25 | req.query.tag | a user-provided value |
|
||||
| mongodb.js:112:14:112:18 | query | mongodb.js:107:17:107:29 | queries.title | mongodb.js:112:14:112:18 | query | This query depends on $@. | mongodb.js:107:17:107:29 | queries.title | a user-provided value |
|
||||
| mongodb_bodySafe.js:29:16:29:20 | query | mongodb_bodySafe.js:24:19:24:33 | req.query.title | mongodb_bodySafe.js:29:16:29:20 | query | This query depends on $@. | mongodb_bodySafe.js:24:19:24:33 | req.query.title | a user-provided value |
|
||||
| mongoose.js:24:24:24:30 | [query] | mongoose.js:21:19:21:26 | req.body | mongoose.js:24:24:24:30 | [query] | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
|
||||
| mongoose.js:27:20:27:24 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:27:20:27:24 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
|
||||
|
||||
@@ -84,3 +84,31 @@ app.post("/logs/count-by-tag", (req, res) => {
|
||||
// NOT OK: query is tainted by user-provided object value
|
||||
.count({ tags: tag });
|
||||
});
|
||||
|
||||
|
||||
app.get('/:id', (req, res) => {
|
||||
useParams(req.param);
|
||||
});
|
||||
function useParams(params) {
|
||||
let query = { id: params.id };
|
||||
MongoClient.connect('mongodb://localhost:27017/test', (err, db) => {
|
||||
let doc = db.collection('doc');
|
||||
|
||||
// OK: query is tainted, but only by string value
|
||||
doc.find(query);
|
||||
});
|
||||
}
|
||||
|
||||
app.post('/documents/find', (req, res) => {
|
||||
useQuery(req.query);
|
||||
});
|
||||
function useQuery(queries) {
|
||||
const query = {};
|
||||
query.title = queries.title;
|
||||
MongoClient.connect('mongodb://localhost:27017/test', (err, db) => {
|
||||
let doc = db.collection('doc');
|
||||
|
||||
// NOT OK: query is tainted by user-provided object value
|
||||
doc.find(query);
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,23 @@
|
||||
nodes
|
||||
| sanitizer.js:2:9:2:25 | url |
|
||||
| sanitizer.js:2:15:2:25 | window.name |
|
||||
| sanitizer.js:2:15:2:25 | window.name |
|
||||
| sanitizer.js:4:27:4:29 | url |
|
||||
| sanitizer.js:4:27:4:29 | url |
|
||||
| sanitizer.js:16:27:16:29 | url |
|
||||
| sanitizer.js:16:27:16:29 | url |
|
||||
| sanitizer.js:19:27:19:29 | url |
|
||||
| sanitizer.js:19:27:19:29 | url |
|
||||
| sanitizer.js:22:27:22:29 | url |
|
||||
| sanitizer.js:22:27:22:29 | url |
|
||||
| sanitizer.js:25:27:25:29 | url |
|
||||
| sanitizer.js:25:27:25:29 | url |
|
||||
| sanitizer.js:28:27:28:29 | url |
|
||||
| sanitizer.js:28:27:28:29 | url |
|
||||
| sanitizer.js:31:27:31:29 | url |
|
||||
| sanitizer.js:31:27:31:29 | url |
|
||||
| sanitizer.js:37:27:37:29 | url |
|
||||
| sanitizer.js:37:27:37:29 | url |
|
||||
| tst2.js:2:7:2:33 | href |
|
||||
| tst2.js:2:7:2:33 | href |
|
||||
| tst2.js:2:14:2:28 | window.location |
|
||||
@@ -80,6 +99,24 @@ nodes
|
||||
| tst.js:6:34:6:50 | document.location |
|
||||
| tst.js:6:34:6:55 | documen ... on.href |
|
||||
edges
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:4:27:4:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:4:27:4:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:16:27:16:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:16:27:16:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:19:27:19:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:19:27:19:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:22:27:22:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:22:27:22:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:25:27:25:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:25:27:25:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:28:27:28:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:28:27:28:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:31:27:31:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:31:27:31:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:37:27:37:29 | url |
|
||||
| sanitizer.js:2:9:2:25 | url | sanitizer.js:37:27:37:29 | url |
|
||||
| sanitizer.js:2:15:2:25 | window.name | sanitizer.js:2:9:2:25 | url |
|
||||
| sanitizer.js:2:15:2:25 | window.name | sanitizer.js:2:9:2:25 | url |
|
||||
| tst2.js:2:7:2:33 | href | tst2.js:4:21:4:24 | href |
|
||||
| tst2.js:2:7:2:33 | href | tst2.js:4:21:4:24 | href |
|
||||
| tst2.js:2:14:2:28 | window.location | tst2.js:2:14:2:33 | window.location.href |
|
||||
@@ -155,6 +192,14 @@ edges
|
||||
| tst.js:6:34:6:50 | document.location | tst.js:6:34:6:55 | documen ... on.href |
|
||||
| tst.js:6:34:6:55 | documen ... on.href | tst.js:6:20:6:56 | indirec ... n.href) |
|
||||
#select
|
||||
| sanitizer.js:4:27:4:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:4:27:4:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
|
||||
| sanitizer.js:16:27:16:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:16:27:16:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
|
||||
| sanitizer.js:19:27:19:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:19:27:19:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
|
||||
| sanitizer.js:22:27:22:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:22:27:22:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
|
||||
| sanitizer.js:25:27:25:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:25:27:25:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
|
||||
| sanitizer.js:28:27:28:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:28:27:28:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
|
||||
| sanitizer.js:31:27:31:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:31:27:31:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
|
||||
| sanitizer.js:37:27:37:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:37:27:37:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
|
||||
| tst2.js:4:21:4:55 | href.su ... '?')+1) | tst2.js:2:14:2:28 | window.location | tst2.js:4:21:4:55 | href.su ... '?')+1) | Untrusted URL redirection due to $@. | tst2.js:2:14:2:28 | window.location | user-provided value |
|
||||
| tst6.js:4:21:4:28 | redirect | tst6.js:2:18:2:45 | $locati ... irect') | tst6.js:4:21:4:28 | redirect | Untrusted URL redirection due to $@. | tst6.js:2:18:2:45 | $locati ... irect') | user-provided value |
|
||||
| tst6.js:6:17:6:24 | redirect | tst6.js:2:18:2:45 | $locati ... irect') | tst6.js:6:17:6:24 | redirect | Untrusted URL redirection due to $@. | tst6.js:2:18:2:45 | $locati ... irect') | user-provided value |
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
function f() {
|
||||
let url = window.name;
|
||||
if (url.startsWith('https://example.com')) {
|
||||
window.location = url; // NOT OK - can be example.com.evil.com
|
||||
}
|
||||
if (url.startsWith('https://example.com/')) {
|
||||
window.location = url; // OK
|
||||
}
|
||||
if (url.startsWith('https://example.com//')) {
|
||||
window.location = url; // OK
|
||||
}
|
||||
if (url.startsWith('https://example.com/foo')) {
|
||||
window.location = url; // OK
|
||||
}
|
||||
if (url.startsWith('https://')) {
|
||||
window.location = url; // NOT OK - does not restrict hostname
|
||||
}
|
||||
if (url.startsWith('https:/')) {
|
||||
window.location = url; // NOT OK - does not restrict hostname
|
||||
}
|
||||
if (url.startsWith('https:')) {
|
||||
window.location = url; // NOT OK - does not restrict hostname
|
||||
}
|
||||
if (url.startsWith('/')) {
|
||||
window.location = url; // NOT OK - can be //evil.com
|
||||
}
|
||||
if (url.startsWith('//')) {
|
||||
window.location = url; // NOT OK - can be //evil.com
|
||||
}
|
||||
if (url.startsWith('//example.com')) {
|
||||
window.location = url; // NOT OK - can be //example.com.evil.com
|
||||
}
|
||||
if (url.startsWith('//example.com/')) {
|
||||
window.location = url; // OK
|
||||
}
|
||||
if (url.endsWith('https://example.com/')) {
|
||||
window.location = url; // NOT OK - could be evil.com?x=https://example.com/
|
||||
}
|
||||
let basedir = whatever() ? 'foo' : 'bar';
|
||||
if (url.startsWith('https://example.com/' + basedir)) {
|
||||
window.location = url; // OK - the whole prefix is not known, but enough to restrict hostname
|
||||
}
|
||||
}
|
||||
@@ -13,4 +13,6 @@
|
||||
- security
|
||||
- exclude:
|
||||
deprecated: //
|
||||
- exclude:
|
||||
query path: /^experimental\/.*/
|
||||
|
||||
|
||||
@@ -21,3 +21,5 @@
|
||||
- file-classifier
|
||||
- exclude:
|
||||
deprecated: //
|
||||
- exclude:
|
||||
query path: /^experimental\/.*/
|
||||
|
||||
@@ -16,3 +16,6 @@
|
||||
- warning
|
||||
- exclude:
|
||||
deprecated: //
|
||||
- exclude:
|
||||
query path: /^experimental\/.*/
|
||||
|
||||
|
||||
@@ -21,4 +21,6 @@
|
||||
- security
|
||||
- exclude:
|
||||
deprecated: //
|
||||
- exclude:
|
||||
query path: /^experimental\/.*/
|
||||
|
||||
|
||||
@@ -11,6 +11,6 @@ import python
|
||||
|
||||
from ExceptStmt ex, ClassValue cls
|
||||
where
|
||||
cls.getName() = "MyExceptionClass" and
|
||||
ex.getType().pointsTo(cls)
|
||||
cls.getName() = "MyExceptionClass" and
|
||||
ex.getType().pointsTo(cls)
|
||||
select ex
|
||||
|
||||
@@ -12,7 +12,7 @@ import python
|
||||
|
||||
from IfExp e, ClassObject cls1, ClassObject cls2
|
||||
where
|
||||
e.getBody().refersTo(_, cls1, _) and
|
||||
e.getOrelse().refersTo(_, cls2, _) and
|
||||
cls1 != cls2
|
||||
e.getBody().refersTo(_, cls1, _) and
|
||||
e.getOrelse().refersTo(_, cls2, _) and
|
||||
cls1 != cls2
|
||||
select e
|
||||
|
||||
@@ -14,8 +14,8 @@ import python
|
||||
|
||||
from If i
|
||||
where
|
||||
not exists(Stmt s |
|
||||
i.getStmt(_) = s and
|
||||
not s instanceof Pass
|
||||
)
|
||||
not exists(Stmt s |
|
||||
i.getStmt(_) = s and
|
||||
not s instanceof Pass
|
||||
)
|
||||
select i
|
||||
|
||||
@@ -14,6 +14,6 @@ import python
|
||||
|
||||
from ClassObject sub, ClassObject base
|
||||
where
|
||||
base.getName() = "MyClass" and
|
||||
sub.getABaseType() = base
|
||||
base.getName() = "MyClass" and
|
||||
sub.getABaseType() = base
|
||||
select sub
|
||||
|
||||
@@ -10,6 +10,6 @@ import python
|
||||
|
||||
from AstNode call, PythonFunctionValue method
|
||||
where
|
||||
method.getQualifiedName() = "MyClass.methodName" and
|
||||
method.getACall().getNode() = call
|
||||
method.getQualifiedName() = "MyClass.methodName" and
|
||||
method.getACall().getNode() = call
|
||||
select call
|
||||
|
||||
@@ -11,6 +11,6 @@ import python
|
||||
|
||||
from Call new, ClassValue cls
|
||||
where
|
||||
cls.getName() = "MyClass" and
|
||||
new.getFunc().pointsTo(cls)
|
||||
cls.getName() = "MyClass" and
|
||||
new.getFunc().pointsTo(cls)
|
||||
select new
|
||||
|
||||
@@ -10,6 +10,6 @@ import python
|
||||
|
||||
from FunctionObject override, FunctionObject base
|
||||
where
|
||||
base.getQualifiedName() = "MyClass.methodName" and
|
||||
override.overrides(base)
|
||||
base.getQualifiedName() = "MyClass.methodName" and
|
||||
override.overrides(base)
|
||||
select override
|
||||
|
||||
@@ -9,9 +9,9 @@ import python
|
||||
|
||||
from AstNode print
|
||||
where
|
||||
/* Python 2 without `from __future__ import print_function` */
|
||||
print instanceof Print
|
||||
or
|
||||
/* Python 3 or with `from __future__ import print_function` */
|
||||
print.(Call).getFunc().pointsTo(Value::named("print"))
|
||||
/* Python 2 without `from __future__ import print_function` */
|
||||
print instanceof Print
|
||||
or
|
||||
/* Python 3 or with `from __future__ import print_function` */
|
||||
print.(Call).getFunc().pointsTo(Value::named("print"))
|
||||
select print
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
import python
|
||||
|
||||
predicate is_private(Attribute a) {
|
||||
a.getName().matches("\\_%") and
|
||||
not a.getName().matches("\\_\\_%\\_\\_")
|
||||
a.getName().matches("\\_%") and
|
||||
not a.getName().matches("\\_\\_%\\_\\_")
|
||||
}
|
||||
|
||||
from Attribute access
|
||||
where
|
||||
is_private(access) and
|
||||
not access.getObject().(Name).getId() = "self"
|
||||
is_private(access) and
|
||||
not access.getObject().(Name).getId() = "self"
|
||||
select access
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user