Skip to content

Commit 5898615

Browse files
authored
Merge pull request github#11420 from github/felicitymay-8441-query-guides-java
LGTM deprecation: updates to CodeQL for Java articles
2 parents 9780990 + 0624324 commit 5898615

File tree

6 files changed

+102
-61
lines changed

6 files changed

+102
-61
lines changed

docs/codeql/codeql-language-guides/annotations-in-java.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ We could then write this query to find all ``@SuppressWarnings`` annotations att
5151
anntp.hasQualifiedName("java.lang", "SuppressWarnings")
5252
select ann, ann.getValue("value")
5353
54-
➤ `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.
54+
If the codebase you are analyzing uses the ``@SuppressWarnings`` annotation, you can check the ``value``\ s of the annotation element returned by the query. They should use the ``"rawtypes"`` value described above.
5555

5656
As another example, this query finds all annotation types that only have a single annotation element, which has name ``value``:
5757

@@ -66,8 +66,6 @@ As another example, this query finds all annotation types that only have a singl
6666
)
6767
select anntp
6868
69-
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/2145264152490258283/>`__.
70-
7169
Example: Finding missing ``@Override`` annotations
7270
--------------------------------------------------
7371

@@ -124,7 +122,7 @@ This makes it very easy to write our query for finding methods that override ano
124122
not overriding.getAnAnnotation() instanceof OverrideAnnotation
125123
select overriding, "Method overrides another method, but does not have an @Override annotation."
126124
127-
➤ `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.
125+
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.
128126

129127
Example: Finding calls to deprecated methods
130128
--------------------------------------------
@@ -237,7 +235,7 @@ Now we can extend our query to filter out calls in methods carrying a ``Suppress
237235
and not call.getCaller().getAnAnnotation() instanceof SuppressDeprecationWarningAnnotation
238236
select call, "This call invokes a deprecated method."
239237
240-
➤ `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.
238+
It's fairly common for projects to contain calls to methods that appear to be deprecated.
241239

242240
Further reading
243241
---------------

docs/codeql/codeql-language-guides/codeql-for-java.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
2626
working-with-source-locations
2727
abstract-syntax-tree-classes-for-working-with-java-programs
2828

29-
- :doc:`Basic query for Java code <basic-query-for-java-code>`: Learn to write and run a simple CodeQL query using LGTM.
29+
- :doc:`Basic query for Java code <basic-query-for-java-code>`: Learn to write and run a simple CodeQL query.
3030

3131
- :doc:`CodeQL library for Java <codeql-library-for-java>`: When analyzing Java code, you can use the large collection of classes in the CodeQL library for Java.
3232

docs/codeql/codeql-language-guides/codeql-library-for-java.rst

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ For example, the following query finds all variables of type ``int`` in the prog
7070
pt.hasName("int")
7171
select v
7272
73-
➤ `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``.
73+
You're likely to get many results when you run this query because most projects contain many variables of type ``int``.
7474

7575
Reference types are also categorized according to their declaration scope:
7676

@@ -87,7 +87,7 @@ For instance, this query finds all top-level types whose name is not the same as
8787
where tl.getName() != tl.getCompilationUnit().getName()
8888
select tl
8989
90-
➤ `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.
90+
You will typically see this pattern in the source code of a repository, with many more instances in the files referenced by the source code.
9191

9292
Several more specialized classes are available as well:
9393

@@ -109,7 +109,7 @@ As an example, we can write a query that finds all nested classes that directly
109109
where nc.getASupertype() instanceof TypeObject
110110
select nc
111111
112-
➤ `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.
112+
You're likely to get many results when you run this query because many projects include nested classes that extend ``Object`` directly.
113113

114114
Generics
115115
~~~~~~~~
@@ -143,8 +143,6 @@ For instance, we could use the following query to find all parameterized instanc
143143
pt.getSourceDeclaration() = map
144144
select pt
145145
146-
➤ `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.
147-
148146
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:
149147

150148
.. code-block:: java
@@ -166,8 +164,6 @@ As an example, the following query finds all type variables with type bound ``Nu
166164
tb.getType().hasQualifiedName("java.lang", "Number")
167165
select tv
168166
169-
➤ `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.
170-
171167
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``:
172168

173169
.. code-block:: ql
@@ -179,8 +175,6 @@ For dealing with legacy code that is unaware of generics, every generic type has
179175
rt.getSourceDeclaration().hasQualifiedName("java.util", "Map")
180176
select v
181177
182-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/4032913402499547882/>`__. Many projects have variables of raw type ``Map``.
183-
184178
For example, in the following code snippet this query would find ``m1``, but not ``m2``:
185179

186180
.. code-block:: java
@@ -230,7 +224,7 @@ For example, the following query finds all expressions whose parents are ``retur
230224
where e.getParent() instanceof ReturnStmt
231225
select e
232226
233-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1947757851560375919/>`__. Many projects have examples of ``return`` statements with child expressions.
227+
Many projects have examples of ``return`` statements with child expressions.
234228

235229
Therefore, if the program contains a return statement ``return x + y;``, this query will return ``x + y``.
236230

@@ -244,7 +238,7 @@ As another example, the following query finds statements whose parent is an ``if
244238
where s.getParent() instanceof IfStmt
245239
select s
246240
247-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1989464153689219612/>`__. Many projects have examples of ``if`` statements with child statements.
241+
Many projects have examples of ``if`` statements with child statements.
248242

249243
This query will find both ``then`` branches and ``else`` branches of all ``if`` statements in the program.
250244

@@ -258,8 +252,6 @@ Finally, here is a query that finds method bodies:
258252
where s.getParent() instanceof Method
259253
select s
260254
261-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1016821702972128245/>`__. Most projects have many method bodies.
262-
263255
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.
264256

265257
For more information on working with AST classes, see the :doc:`article on overflow-prone comparisons in Java <overflow-prone-comparisons-in-java>`.
@@ -278,7 +270,7 @@ For annotations, class ``Annotatable`` is a superclass of all program elements t
278270
from Constructor c
279271
select c.getAnAnnotation()
280272
281-
➤ `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.
273+
You may see examples where annotations are used to suppress warnings or to mark code as deprecated.
282274

283275
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:
284276

@@ -292,7 +284,7 @@ These annotations are represented by class ``Annotation``. An annotation is simp
292284
anntp.hasQualifiedName("java.lang", "Deprecated")
293285
select ann
294286
295-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/5393027107459215059/>`__. Only constructors with the ``@Deprecated`` annotation are reported this time.
287+
Only constructors with the ``@Deprecated`` annotation are reported this time.
296288

297289
For more information on working with annotations, see the :doc:`article on annotations <annotations-in-java>`.
298290

@@ -307,7 +299,7 @@ For Javadoc, class ``Element`` has a member predicate ``getDoc`` that returns a
307299
jdoc = f.getDoc().getJavadoc()
308300
select jdoc
309301
310-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/6022769142134600659/>`__. You can see this pattern in many projects.
302+
You can see this pattern in many projects.
311303

312304
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:
313305

@@ -321,8 +313,6 @@ Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocEle
321313
at.getParent+() = jdoc
322314
select at
323315
324-
➤ `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.
325-
326316
.. pull-quote::
327317

328318
Note
@@ -349,7 +339,7 @@ For example, the following query finds methods with a `cyclomatic complexity <ht
349339
mc.getCyclomaticComplexity() > 40
350340
select m
351341
352-
➤ `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.
342+
Most large projects include some methods with a very high cyclomatic complexity. These methods are likely to be difficult to understand and test.
353343

354344
Call graph
355345
----------
@@ -369,8 +359,6 @@ We can use predicate ``Call.getCallee`` to find out which method or constructor
369359
m.hasName("println")
370360
select c
371361
372-
➤ `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.
373-
374362
Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So we can find methods and constructors that are never called using this query:
375363

376364
.. code-block:: ql
@@ -381,7 +369,7 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So
381369
where not exists(c.getAReference())
382370
select c
383371
384-
➤ `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 <navigating-the-call-graph>`."
372+
Codebases often 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 <navigating-the-call-graph>`."
385373

386374
For more information about callables and calls, see the :doc:`article on the call graph <navigating-the-call-graph>`.
387375

docs/codeql/codeql-language-guides/javadoc.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ Now we can write a query for finding all callables ``c`` and ``@throws`` tags ``
149149
not mayThrow(c, exn)
150150
select tt, "Spurious @throws tag."
151151
152-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1258570917227966396/>`__. This finds several results in the LGTM.com demo projects.
153-
154152
Improvements
155153
~~~~~~~~~~~~
156154

@@ -216,7 +214,7 @@ The first case can be covered by changing ``getDocumentedException`` to use the
216214
(result.hasName(tt.getExceptionName()) and visibleIn(tt.getFile(), result))
217215
}
218216
219-
➤ `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.
217+
This query should find many fewer, more interesting results.
220218

221219
Currently, ``visibleIn`` only considers single-type imports, but you could extend it with support for other kinds of imports.
222220

docs/codeql/codeql-language-guides/overflow-prone-comparisons-in-java.rst

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ We'll start by writing a query that finds less-than expressions (CodeQL class ``
4444
expr.getRightOperand().getType().hasName("long")
4545
select expr
4646
47-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/490866529746563234/>`__. This query usually finds results on most projects.
47+
This query usually finds results on most codebases.
4848

4949
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:
5050

@@ -59,7 +59,7 @@ Notice that we use the predicate ``getType`` (available on all subclasses of ``E
5959
not expr.getAnOperand().isCompileTimeConstant()
6060
select expr
6161
62-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/4315986481180063825/>`__. Notice that fewer results are found.
62+
Notice that fewer results are found.
6363

6464
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.
6565

@@ -113,16 +113,44 @@ Now we rewrite our query to make use of these new classes:
113113

114114
.. code-block:: ql
115115
116-
import Java
117-
118-
// Insert the class definitions from above
119-
120-
from OverflowProneComparison expr
121-
where exists(LoopStmt l | l.getCondition().getAChildExpr*() = expr) and
122-
not expr.getAnOperand().isCompileTimeConstant()
123-
select expr
124-
125-
➤ `See the full query in the query console on LGTM.com <https://lgtm.com/query/506868054626167462/>`__.
116+
import java
117+
118+
// Return the width (in bits) of a given integral type
119+
int width(PrimitiveType pt) {
120+
(pt.hasName("byte") and result=8) or
121+
(pt.hasName("short") and result=16) or
122+
(pt.hasName("char") and result=16) or
123+
(pt.hasName("int") and result=32) or
124+
(pt.hasName("long") and result=64)
125+
}
126+
127+
// Find any comparison where the width of the type on the smaller end of
128+
// the comparison is less than the width of the type on the greater end
129+
abstract class OverflowProneComparison extends ComparisonExpr {
130+
Expr getLesserOperand() { none() }
131+
Expr getGreaterOperand() { none() }
132+
}
133+
134+
// Return `<=` and `<` comparisons
135+
class LTOverflowProneComparison extends OverflowProneComparison {
136+
LTOverflowProneComparison() {
137+
(this instanceof LEExpr or this instanceof LTExpr) and
138+
width(this.getLeftOperand().getType()) < width(this.getRightOperand().getType())
139+
}
140+
}
141+
142+
// Return `>=` and `>` comparisons
143+
class GTOverflowProneComparison extends OverflowProneComparison {
144+
GTOverflowProneComparison() {
145+
(this instanceof GEExpr or this instanceof GTExpr) and
146+
width(this.getRightOperand().getType()) < width(this.getLeftOperand().getType())
147+
}
148+
}
149+
150+
from OverflowProneComparison expr
151+
where exists(LoopStmt l | l.getCondition().getAChildExpr*() = expr) and
152+
not expr.getAnOperand().isCompileTimeConstant()
153+
select expr
126154
127155
Further reading
128156
---------------

0 commit comments

Comments
 (0)