Skip to content

Commit 88f9685

Browse files
committed
Merge rc/1.21 into master
2 parents f70e7d7 + 7a510f5 commit 88f9685

File tree

20 files changed

+162
-51
lines changed

20 files changed

+162
-51
lines changed

javascript/extractor/src/com/semmle/js/parser/TypeScriptParser.java

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,21 @@
3333
import java.io.OutputStreamWriter;
3434
import java.lang.ProcessBuilder.Redirect;
3535
import java.util.ArrayList;
36+
import java.util.Arrays;
37+
import java.util.Collections;
3638
import java.util.List;
3739

3840
/**
3941
* The Java half of our wrapper for invoking the TypeScript parser.
4042
*
4143
* <p>The Node.js half of the wrapper is expected to live at {@code
4244
* $SEMMLE_DIST/tools/typescript-parser-wrapper/main.js}; non-standard locations can be configured
43-
* using the property {@link #PARSER_WRAPPER_PATH_ENV_VAR}.
45+
* using the property {@value #PARSER_WRAPPER_PATH_ENV_VAR}.
46+
*
47+
* <p>The script launches the Node.js wrapper in the Node.js runtime, looking for {@code node}
48+
* on the {@code PATH} by default. Non-standard locations can be configured using the property
49+
* {@value #TYPESCRIPT_NODE_RUNTIME_VAR}, and additional arguments can be configured using the
50+
* property {@value #TYPESCRIPT_NODE_RUNTIME_EXTRA_ARGS_VAR}.
4451
*
4552
* <p>The script is started upon parsing the first TypeScript file and then is kept running in the
4653
* background, passing it requests for parsing files and getting JSON-encoded ASTs as responses.
@@ -52,6 +59,18 @@ public class TypeScriptParser {
5259
*/
5360
public static final String PARSER_WRAPPER_PATH_ENV_VAR = "SEMMLE_TYPESCRIPT_PARSER_WRAPPER";
5461

62+
/**
63+
* An environment variable that can be set to indicate the location of the Node.js runtime,
64+
* as an alternative to adding Node to the PATH.
65+
*/
66+
public static final String TYPESCRIPT_NODE_RUNTIME_VAR = "SEMMLE_TYPESCRIPT_NODE_RUNTIME";
67+
68+
/**
69+
* An environment variable that can be set to provide additional arguments to the Node.js runtime
70+
* each time it is invoked. Arguments should be separated by spaces.
71+
*/
72+
public static final String TYPESCRIPT_NODE_RUNTIME_EXTRA_ARGS_VAR = "SEMMLE_TYPESCRIPT_NODE_RUNTIME_EXTRA_ARGS";
73+
5574
/**
5675
* An environment variable that can be set to specify a timeout to use when verifying the
5776
* TypeScript installation, in milliseconds. Default is 10000.
@@ -91,6 +110,15 @@ public class TypeScriptParser {
91110

92111
private String nodeJsVersionString;
93112

113+
/** Command to launch the Node.js runtime. Initialised by {@link #verifyNodeInstallation}. */
114+
private String nodeJsRuntime;
115+
116+
/**
117+
* Arguments to pass to the Node.js runtime each time it is invoked.
118+
* Initialised by {@link #verifyNodeInstallation}.
119+
*/
120+
private List<String> nodeJsRuntimeExtraArgs = Collections.emptyList();
121+
94122
/** If non-zero, we use this instead of relying on the corresponding environment variable. */
95123
private int typescriptRam = 0;
96124

@@ -102,12 +130,16 @@ public void setTypescriptRam(int megabytes) {
102130
/**
103131
* Verifies that Node.js and TypeScript are installed and throws an exception otherwise.
104132
*
105-
* @param verbose if true, log the version strings and NODE_PATH.
133+
* @param verbose if true, log the Node.js executable path, version strings, and any additional arguments.
106134
*/
107135
public void verifyInstallation(boolean verbose) {
108136
verifyNodeInstallation();
109137
if (verbose) {
138+
System.out.println("Found Node.js at: " + nodeJsRuntime);
110139
System.out.println("Found Node.js version: " + nodeJsVersionString);
140+
if (!nodeJsRuntimeExtraArgs.isEmpty()) {
141+
System.out.println("Additional arguments for Node.js: " + nodeJsRuntimeExtraArgs);
142+
}
111143
}
112144
}
113145

@@ -117,7 +149,24 @@ public String verifyNodeInstallation() {
117149

118150
ByteArrayOutputStream out = new ByteArrayOutputStream();
119151
ByteArrayOutputStream err = new ByteArrayOutputStream();
120-
Builder b = new Builder(out, err, getParserWrapper().getParentFile(), "node", "--version");
152+
153+
// Determine where to find the Node.js runtime.
154+
String explicitNodeJsRuntime = Env.systemEnv().get(TYPESCRIPT_NODE_RUNTIME_VAR);
155+
if (explicitNodeJsRuntime != null) {
156+
// Use the specified Node.js executable.
157+
nodeJsRuntime = explicitNodeJsRuntime;
158+
} else {
159+
// Look for `node` on the PATH.
160+
nodeJsRuntime = "node";
161+
}
162+
163+
// Determine any additional arguments to be passed to Node.js each time it's called.
164+
String extraArgs = Env.systemEnv().get(TYPESCRIPT_NODE_RUNTIME_EXTRA_ARGS_VAR);
165+
if (extraArgs != null) {
166+
nodeJsRuntimeExtraArgs = Arrays.asList(extraArgs.split("\\s+"));
167+
}
168+
169+
Builder b = new Builder(getNodeJsRuntimeInvocation("--version"), out, err, getParserWrapper().getParentFile());
121170
b.expectFailure(); // We want to do our own logging in case of an error.
122171

123172
int timeout = Env.systemEnv().getInt(TYPESCRIPT_TIMEOUT_VAR, 10000);
@@ -144,6 +193,21 @@ public String verifyNodeInstallation() {
144193
}
145194
}
146195

196+
/**
197+
* Gets a command line to invoke the Node.js runtime.
198+
* Any arguments in {@link TypeScriptParser#nodeJsRuntimeExtraArgs}
199+
* are passed first, followed by those in {@code args}.
200+
*/
201+
private List<String> getNodeJsRuntimeInvocation(String ...args) {
202+
List<String> result = new ArrayList<>();
203+
result.add(nodeJsRuntime);
204+
result.addAll(nodeJsRuntimeExtraArgs);
205+
for(String arg : args) {
206+
result.add(arg);
207+
}
208+
return result;
209+
}
210+
147211
private static int getMegabyteCountFromPrefixedEnv(String suffix, int defaultValue) {
148212
String envVar = "SEMMLE_" + suffix;
149213
String value = Env.systemEnv().get(envVar);
@@ -172,10 +236,11 @@ private void setupParserWrapper() {
172236
int reserveMemoryMb = getMegabyteCountFromPrefixedEnv(TYPESCRIPT_RAM_RESERVE_SUFFIX, 400);
173237

174238
File parserWrapper = getParserWrapper();
175-
List<String> cmd = new ArrayList<>();
176-
cmd.add("node");
177-
cmd.add("--max_old_space_size=" + (mainMemoryMb + reserveMemoryMb));
178-
cmd.add(parserWrapper.getAbsolutePath());
239+
240+
List<String> cmd = getNodeJsRuntimeInvocation(
241+
"--max_old_space_size=" + (mainMemoryMb + reserveMemoryMb),
242+
parserWrapper.getAbsolutePath()
243+
);
179244
ProcessBuilder pb = new ProcessBuilder(cmd);
180245
parserWrapperCommand = StringUtil.glue(" ", cmd);
181246
pb.environment().put("SEMMLE_TYPESCRIPT_MEMORY_THRESHOLD", "" + mainMemoryMb);

python/ql/src/semmle/python/objects/Callables.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
161161

162162
override predicate contextSensitiveCallee() { any() }
163163

164+
override predicate useOriginAsLegacyObject() { none() }
165+
164166
}
165167

166168

@@ -284,6 +286,8 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc
284286

285287
override predicate contextSensitiveCallee() { none() }
286288

289+
override predicate useOriginAsLegacyObject() { none() }
290+
287291
}
288292

289293
/** Class representing methods of built-in classes (otherwise known as method-descriptors) such as `list.append`.
@@ -376,6 +380,8 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod
376380

377381
override predicate contextSensitiveCallee() { none() }
378382

383+
override predicate useOriginAsLegacyObject() { none() }
384+
379385
}
380386

381387
/** Class representing bound-methods.
@@ -461,6 +467,8 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod {
461467
function = this.getFunction() and offset = 1
462468
}
463469

470+
override predicate useOriginAsLegacyObject() { any() }
471+
464472
override predicate contextSensitiveCallee() {
465473
this.getFunction().contextSensitiveCallee()
466474
}

python/ql/src/semmle/python/objects/Classes.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ abstract class ClassObjectInternal extends ObjectInternal {
9292

9393
override predicate contextSensitiveCallee() { none() }
9494

95+
override predicate useOriginAsLegacyObject() { none() }
96+
9597
/* Classes aren't usually iterable, but can e.g. Enums */
9698
override ObjectInternal getIterNext() { result = ObjectInternal::unknown() }
9799

python/ql/src/semmle/python/objects/Constants.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ abstract class ConstantObjectInternal extends ObjectInternal {
7171

7272
override predicate contextSensitiveCallee() { none() }
7373

74+
override predicate useOriginAsLegacyObject() { none() }
75+
7476
}
7577

7678
private abstract class BooleanObjectInternal extends ConstantObjectInternal {

python/ql/src/semmle/python/objects/Descriptors.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ class PropertyInternal extends ObjectInternal, TProperty {
9393

9494
override predicate contextSensitiveCallee() { none() }
9595

96+
override predicate useOriginAsLegacyObject() { none() }
97+
9698
/* Properties aren't iterable */
9799
override ObjectInternal getIterNext() { none() }
98100

@@ -183,6 +185,8 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod {
183185

184186
override predicate contextSensitiveCallee() { none() }
185187

188+
override predicate useOriginAsLegacyObject() { none() }
189+
186190
/* Classmethods aren't iterable */
187191
override ObjectInternal getIterNext() { none() }
188192

@@ -259,6 +263,8 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod {
259263

260264
override predicate contextSensitiveCallee() { none() }
261265

266+
override predicate useOriginAsLegacyObject() { none() }
267+
262268
/* Staticmethods aren't iterable */
263269
override ObjectInternal getIterNext() { none() }
264270

python/ql/src/semmle/python/objects/Instances.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject {
164164
)
165165
}
166166

167+
override predicate useOriginAsLegacyObject() { none() }
168+
167169
}
168170

169171
/** A class representing context-free instances represented by `self` in the source code
@@ -266,6 +268,8 @@ class SelfInstanceInternal extends TSelfInstance, InstanceObject {
266268
this.getClass().attribute("__init__", init, _)
267269
}
268270

271+
override predicate useOriginAsLegacyObject() { none() }
272+
269273
}
270274

271275
/** A class representing a value that has a known class, but no other information */
@@ -372,6 +376,8 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal {
372376

373377
override predicate contextSensitiveCallee() { none() }
374378

379+
override predicate useOriginAsLegacyObject() { any() }
380+
375381
override ObjectInternal getIterNext() { result = ObjectInternal::unknown() }
376382

377383
}
@@ -482,6 +488,8 @@ class SuperInstance extends TSuperInstance, ObjectInternal {
482488

483489
override predicate contextSensitiveCallee() { none() }
484490

491+
override predicate useOriginAsLegacyObject() { any() }
492+
485493
override ObjectInternal getIterNext() { result = ObjectInternal::unknown() }
486494

487495
}

python/ql/src/semmle/python/objects/Modules.qll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ abstract class ModuleObjectInternal extends ObjectInternal {
5454

5555
override predicate contextSensitiveCallee() { none() }
5656

57+
override predicate useOriginAsLegacyObject() { none() }
58+
5759
/* Modules aren't iterable */
5860
override ObjectInternal getIterNext() { none() }
5961

@@ -313,10 +315,6 @@ class AbsentModuleObjectInternal extends ModuleObjectInternal, TAbsentModule {
313315
none()
314316
}
315317

316-
override predicate isMissing() {
317-
any()
318-
}
319-
320318
}
321319

322320
/** A class representing an attribute of a missing module. */
@@ -402,15 +400,13 @@ class AbsentModuleAttributeObjectInternal extends ObjectInternal, TAbsentModuleA
402400

403401
override predicate subscriptUnknown() { any() }
404402

405-
override predicate isMissing() {
406-
any()
407-
}
408-
409403
/* We know what this is called, but not its innate name */
410404
override string getName() { none() }
411405

412406
override predicate contextSensitiveCallee() { none() }
413407

408+
override predicate useOriginAsLegacyObject() { none() }
409+
414410
/* Modules aren't iterable */
415411
override ObjectInternal getIterNext() { none() }
416412

python/ql/src/semmle/python/objects/ObjectAPI.qll

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,6 @@ class Value extends TObject {
7878
this.(ObjectInternal).isBuiltin()
7979
}
8080

81-
/** Holds if this value represents an entity that is inferred to exist,
82-
* but missing from the database.
83-
* Most commonly, this is a module that is imported, but wasn't present during extraction.
84-
*/
85-
predicate isMissing() {
86-
this.(ObjectInternal).isMissing()
87-
}
88-
8981
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
9082
this.(ObjectInternal).getOrigin().getLocation().hasLocationInfo(filepath, bl, bc, el, ec)
9183
or

python/ql/src/semmle/python/objects/ObjectInternal.qll

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,12 @@ class ObjectInternal extends TObject {
155155
*/
156156
predicate functionAndOffset(CallableObjectInternal function, int offset) { none() }
157157

158-
/** Holds if this 'object' represents an entity that is inferred to exist
159-
* but is missing from the database */
160-
predicate isMissing() {
161-
none()
162-
}
158+
/** Holds if this 'object' represents an entity that should be exposed to the legacy points_to API
159+
* This should hold for almost all objects that do not have an underlying DB object representing their source,
160+
* for example `super` objects and bound-method. This should not hold for objects that are inferred to exists by
161+
* an import statements or the like, but which aren't in the database. */
162+
/* This predicate can be removed when the legacy points_to API is removed. */
163+
abstract predicate useOriginAsLegacyObject();
163164

164165
/** Gets the name of this of this object if it has a meaningful name.
165166
* Note that the name of an object is not necessarily the name by which it is called
@@ -260,6 +261,8 @@ class BuiltinOpaqueObjectInternal extends ObjectInternal, TBuiltinOpaqueObject {
260261

261262
override predicate contextSensitiveCallee() { none() }
262263

264+
override predicate useOriginAsLegacyObject() { none() }
265+
263266
override ObjectInternal getIterNext() { result = ObjectInternal::unknown() }
264267

265268
}
@@ -341,6 +344,8 @@ class UnknownInternal extends ObjectInternal, TUnknown {
341344

342345
override predicate contextSensitiveCallee() { none() }
343346

347+
override predicate useOriginAsLegacyObject() { none() }
348+
344349
override ObjectInternal getIterNext() { result = ObjectInternal::unknown() }
345350

346351
}
@@ -421,6 +426,8 @@ class UndefinedInternal extends ObjectInternal, TUndefined {
421426

422427
override string getName() { none() }
423428

429+
override predicate useOriginAsLegacyObject() { none() }
430+
424431
/** Holds if this object requires context to determine the object resulting from a call to it.
425432
* True for most callables. */
426433
override predicate contextSensitiveCallee() { none() }
@@ -608,6 +615,8 @@ class DecoratedFunction extends ObjectInternal, TDecoratedFunction {
608615

609616
override predicate contextSensitiveCallee() { none() }
610617

618+
override predicate useOriginAsLegacyObject() { none() }
619+
611620
}
612621

613622
/** Helper for boolean predicates returning both `true` and `false` */

python/ql/src/semmle/python/objects/Sequences.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ class BuiltinTupleObjectInternal extends TBuiltinTuple, TupleObjectInternal {
121121
result = count(int n | exists(b.getItem(n)))
122122
)
123123
}
124+
125+
override predicate useOriginAsLegacyObject() { none() }
126+
124127
}
125128

126129
/** A tuple declared by a tuple expression in the Python source code */
@@ -152,6 +155,8 @@ class PythonTupleObjectInternal extends TPythonTuple, TupleObjectInternal {
152155
)
153156
}
154157

158+
override predicate useOriginAsLegacyObject() { none() }
159+
155160
}
156161

157162
/** A tuple created by a `*` parameter */
@@ -180,6 +185,9 @@ class VarargsTupleObjectInternal extends TVarargsTuple, TupleObjectInternal {
180185
override int length() {
181186
this = TVarargsTuple(_, _, _, result)
182187
}
188+
189+
override predicate useOriginAsLegacyObject() { any() }
190+
183191
}
184192

185193

@@ -260,4 +268,6 @@ class SysVersionInfoObjectInternal extends TSysVersionInfo, SequenceObjectIntern
260268

261269
override predicate functionAndOffset(CallableObjectInternal function, int offset) { none() }
262270

271+
override predicate useOriginAsLegacyObject() { any() }
272+
263273
}

0 commit comments

Comments
 (0)