Skip to content

Commit 8d9281e

Browse files
ginsbachkaspersv
authored andcommitted
annotate .qll files in java and shared via script
1 parent a519eab commit 8d9281e

File tree

425 files changed

+1134
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

425 files changed

+1134
-0
lines changed

config/annotate-overlay-local.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# This script is used to annotate .qll files with overlay[local?] annotations.
2+
# It will walk the directory tree and annotate most .qll files, skipping only
3+
# some specific cases (e.g., empty files, files that configure dataflow for queries).
4+
# It will also add overlay[caller] annotations to predicates that are pragma[inline]
5+
# and either not private or in a hardcoded list of predicates.
6+
7+
# The script takes a list of languages and processes the corresponding directories.
8+
9+
# Usage: python3 annotate-overlay-local.py <language1> <language2> ...
10+
11+
# The script will modify the files in place and print the changes made.
12+
# The script is designed to be run from the root of the repository.
13+
14+
#!/usr/bin/python3
15+
import sys
16+
import os
17+
from difflib import *
18+
19+
# These are the only two predicates that are pragma[inline], private, and must be
20+
# overlay[caller] in order to successfully compile our internal java queries.
21+
hardcoded_overlay_caller_preds = [
22+
"fwdFlowInCand", "fwdFlowInCandTypeFlowDisabled"]
23+
24+
25+
def filter_out_annotations(filename):
26+
'''
27+
Read the file and strip all existing overlay[...] annotations from the contents.
28+
Return the file modified file content as a list of lines.
29+
'''
30+
overlays = ["local", "local?", "global", "caller"]
31+
annotations = [f"overlay[{t}]" for t in overlays]
32+
with open(filename, 'r') as file_in:
33+
lines = [l for l in file_in if not l.strip() in annotations]
34+
for ann in annotations:
35+
if any(line for line in lines if ann in line):
36+
raise Exception(f"Failed to filter out {ann} from {filename}.")
37+
return lines
38+
39+
40+
def insert_toplevel_maybe_local_anntotation(filename, lines):
41+
'''
42+
Find a suitable place to insert an overlay[local?] annotation at the top of the file.
43+
Return a pair: (string describing action taken, modified content as list of lines).
44+
'''
45+
out_lines = []
46+
status = 0
47+
48+
for line in lines:
49+
if status == 0 and line.rstrip().endswith("module;"):
50+
out_lines.append("overlay[local?]\n")
51+
status = 1
52+
out_lines.append(line)
53+
54+
if status == 1:
55+
return (f"Annotating \"{filename}\" via existing file-level module statement", out_lines)
56+
57+
out_lines = []
58+
empty_line_buffer = []
59+
status = 0
60+
for line in lines:
61+
trimmed = line.strip()
62+
if not trimmed:
63+
empty_line_buffer.append(line)
64+
continue
65+
if status <= 1 and trimmed.endswith("*/"):
66+
status = 2
67+
elif status == 0 and trimmed.startswith("/**"):
68+
status = 1
69+
elif status == 0 and not trimmed.startswith("/*"):
70+
out_lines.append("overlay[local?]\n")
71+
out_lines.append("module;\n")
72+
out_lines.append("\n")
73+
status = 3
74+
elif status == 2 and (trimmed.startswith("import ") or trimmed.startswith("private import ")):
75+
out_lines.append("overlay[local?]\n")
76+
out_lines.append("module;\n")
77+
status = 3
78+
elif status == 2 and (trimmed.startswith("class ") or trimmed.startswith("predicate ")
79+
or trimmed.startswith("module ") or trimmed.startswith("signature ")):
80+
out_lines = ["overlay[local?]\n", "module;\n", "\n"] + out_lines
81+
status = 3
82+
elif status == 2 and trimmed.startswith("/*"):
83+
out_lines.append("overlay[local?]\n")
84+
out_lines.append("module;\n")
85+
status = 3
86+
elif status == 2:
87+
status = 4
88+
if empty_line_buffer:
89+
out_lines += empty_line_buffer
90+
empty_line_buffer = []
91+
out_lines.append(line)
92+
if status == 3:
93+
out_lines += empty_line_buffer
94+
95+
if status == 3:
96+
return (f"Annotating \"{filename}\" after file-level module qldoc", out_lines)
97+
98+
raise Exception(f"Failed to annotate \"{filename}\" as overlay[local?].")
99+
100+
101+
def insert_overlay_caller_annotations(lines):
102+
'''
103+
Mark pragma[inline] predicates as overlay[caller] if they are not declared private
104+
or if they are private but are in the list of hardcoded_overlay_caller_preds.
105+
'''
106+
out_lines = []
107+
for i, line in enumerate(lines):
108+
trimmed = line.strip()
109+
if trimmed == "pragma[inline]":
110+
if (not "private" in lines[i+1] or
111+
any(pred in lines[i+1] for pred in hardcoded_overlay_caller_preds)):
112+
whitespace = line[0: line.find(trimmed)]
113+
out_lines.append(f"{whitespace}overlay[caller]\n")
114+
out_lines.append(line)
115+
return out_lines
116+
117+
118+
def annotate_as_appropriate(filename):
119+
'''
120+
Read file and strip all existing overlay[...] annotations from the contents;
121+
then insert new overlay[...] annotations according to heuristics.
122+
Return a pair: (string describing action taken, modified content as list of lines).
123+
'''
124+
lines = filter_out_annotations(filename)
125+
lines = insert_overlay_caller_annotations(lines)
126+
127+
# These simple heuristics filter out those .qll files that we no _not_ want to annotate
128+
# as overlay[local?]. It is not clear that these heuristics are exactly what we want,
129+
# but they seem to work well enough for now (as determined by speed and accuracy numbers).
130+
if (filename.endswith("Test.qll") or
131+
((filename.endswith("Query.qll") or filename.endswith("Config.qll")) and
132+
any("implements DataFlow::ConfigSig" in line for line in lines))):
133+
return (f"Keeping \"{filename}\" global because it configures dataflow for a query", lines)
134+
elif not any(line for line in lines if line.strip()):
135+
return (f"Keeping \"{filename}\" global because it is empty", lines)
136+
137+
return insert_toplevel_maybe_local_anntotation(filename, lines)
138+
139+
140+
def process_single_file(filename):
141+
'''
142+
Process a single file, annotating it as appropriate and writing the changes back to the file.
143+
'''
144+
annotate_result = annotate_as_appropriate(filename)
145+
146+
old = [line for line in open(filename)]
147+
new = annotate_result[1]
148+
149+
if old != new:
150+
diff = context_diff(old, new, fromfile=filename, tofile=filename)
151+
diff = [line for line in diff]
152+
if diff:
153+
print(annotate_result[0])
154+
for line in diff:
155+
print(line.rstrip())
156+
with open(filename, "w") as out_file:
157+
for line in new:
158+
out_file.write(line)
159+
160+
161+
dirs = []
162+
for lang in sys.argv[1:]:
163+
if lang in ["cpp", "go", "csharp", "java", "javascript", "python", "ruby", "rust", "swift"]:
164+
dirs.append(f"{lang}/ql/lib")
165+
else:
166+
raise Exception(f"Unknown language \"{lang}\".")
167+
168+
if dirs:
169+
dirs.append("shared")
170+
171+
for roots in dirs:
172+
for dirpath, dirnames, filenames in os.walk(roots):
173+
for filename in filenames:
174+
if filename.endswith(".qll") and not dirpath.endswith("tutorial"):
175+
process_single_file(os.path.join(dirpath, filename))

java/ql/lib/Customizations.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@
88
* the `RemoteFlowSource` and `AdditionalTaintStep` classes associated with the security queries
99
* to model frameworks that are not covered by the standard library.
1010
*/
11+
overlay[local?]
12+
module;
1113

1214
import java

java/ql/lib/IDEContextual.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides shared predicates related to contextual queries in the code viewer.
33
*/
4+
overlay[local?]
5+
module;
46

57
import semmle.files.FileSystem
68
private import codeql.util.FileSystem

java/ql/lib/default.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
/** DEPRECATED: use `java.qll` instead. */
2+
overlay[local?]
3+
module;
24

35
import java

java/ql/lib/definitions.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* Provides classes and predicates related to jump-to-definition links
33
* in the code viewer.
44
*/
5+
overlay[local?]
6+
module;
57

68
import java
79
import IDEContextual

java/ql/lib/external/ExternalArtifact.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
overlay[local?]
2+
module;
3+
14
import java
25

36
class ExternalData extends @externalDataElement {

java/ql/lib/java.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/** Provides all default Java QL imports. */
2+
overlay[local?]
3+
module;
24

35
import Customizations
46
import semmle.code.FileSystem

java/ql/lib/semmle/code/FileSystem.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/** Provides classes for working with files and folders. */
2+
overlay[local?]
3+
module;
24

35
import Location
46
private import codeql.util.FileSystem

java/ql/lib/semmle/code/Location.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
*
44
* Locations represent parts of files and are used to map elements to their source location.
55
*/
6+
overlay[local?]
7+
module;
68

79
import FileSystem
810
import semmle.code.java.Element

java/ql/lib/semmle/code/SMAP.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides classes and predicates for working with SMAP files (see JSR-045).
33
*/
4+
overlay[local?]
5+
module;
46

57
import java
68

java/ql/lib/semmle/code/Unit.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
/** Provides the `Unit` class. */
2+
overlay[local?]
3+
module;
24

35
import codeql.util.Unit

java/ql/lib/semmle/code/configfiles/ConfigFiles.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* Provides classes and predicates for working with configuration files, such
33
* as Java `.properties` or `.ini` files.
44
*/
5+
overlay[local?]
6+
module;
57

68
import semmle.code.Location
79

java/ql/lib/semmle/code/java/Annotation.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
* Each annotation type has zero or more annotation elements that contain a
99
* name and possibly a value.
1010
*/
11+
overlay[local?]
12+
module;
1113

1214
import Element
1315
import Expr

java/ql/lib/semmle/code/java/Collections.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* Provides classes and predicates for reasoning about instances of
33
* `java.util.Collection` and their methods.
44
*/
5+
overlay[local?]
6+
module;
57

68
import java
79

java/ql/lib/semmle/code/java/Compilation.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides a class representing individual compiler invocations that occurred during the build.
33
*/
4+
overlay[local?]
5+
module;
46

57
import semmle.code.FileSystem
68

java/ql/lib/semmle/code/java/CompilationUnit.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides classes and predicates for working with Java compilation units.
33
*/
4+
overlay[local?]
5+
module;
46

57
import Element
68
import Package

java/ql/lib/semmle/code/java/Completion.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides classes and predicates for representing completions.
33
*/
4+
overlay[local?]
5+
module;
46

57
/*
68
* A completion represents how a statement or expression terminates.

java/ql/lib/semmle/code/java/Concurrency.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
overlay[local?]
2+
module;
3+
14
import java
25

36
/**

java/ql/lib/semmle/code/java/Constants.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provdides a module to calculate constant integer and boolean values.
33
*/
4+
overlay[local?]
5+
module;
46

57
import java
68

java/ql/lib/semmle/code/java/ControlFlowGraph.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
* statement, an expression, or an exit node for a callable, indicating that
88
* execution of the callable terminates.
99
*/
10+
overlay[local?]
11+
module;
1012

1113
/*
1214
* The implementation is centered around the concept of a _completion_, which

java/ql/lib/semmle/code/java/Conversions.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*
55
* See the Java Language Specification, Section 5, for details.
66
*/
7+
overlay[local?]
8+
module;
79

810
import java
911
import semmle.code.java.arithmetic.Overflow

java/ql/lib/semmle/code/java/Dependency.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides utility predicates for representing dependencies between types.
33
*/
4+
overlay[local?]
5+
module;
46

57
import Type
68
import Generics

java/ql/lib/semmle/code/java/DependencyCounts.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* This library provides utility predicates for representing the number of dependencies between types.
33
*/
4+
overlay[local?]
5+
module;
46

57
import Type
68
import Generics

java/ql/lib/semmle/code/java/Diagnostics.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides classes representing warnings generated during compilation.
33
*/
4+
overlay[local?]
5+
module;
46

57
import java
68

java/ql/lib/semmle/code/java/Element.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides a class that represents named elements in Java programs.
33
*/
4+
overlay[local?]
5+
module;
46

57
import CompilationUnit
68
import semmle.code.Location

java/ql/lib/semmle/code/java/Exception.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides classes and predicates for working with Java exceptions.
33
*/
4+
overlay[local?]
5+
module;
46

57
import Element
68
import Type

java/ql/lib/semmle/code/java/Expr.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Provides classes for working with Java expressions.
33
*/
4+
overlay[local?]
5+
module;
46

57
import java
68
private import semmle.code.java.frameworks.android.Compose

0 commit comments

Comments
 (0)