mirror of
https://github.com/github/codeql.git
synced 2026-01-08 04:00:26 +01:00
JavaScript: Teach extractor to tolerate assignment patterns in AST.
Our database representation of ASTs does not use assignment patterns, instead encoding the relevant information directly in the associated function/loop/assignment. We convert from an AST with assignment patterns to one without during parsing, so the extractor does not expect any assignment patterns to be present in the AST. Due to a bug in the parser, this can currently happen for malformed programs. While we should fix that bug once it gets fixed in Acorn, it also makes sense for the extractor to be more robust, so this PR teaches the `ASTExtractor` pass to raise a parse error when it encounters an assignment pattern, and all other passes to simply ignore them.
This commit is contained in:
@@ -97,8 +97,11 @@ public class DefaultVisitor<C, R> implements Visitor<C, R> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public R visit(AssignmentPattern nd, C q) {
|
||||
throw new CatastrophicError("Assignment patterns should not appear in the AST.");
|
||||
public R visit(AssignmentPattern nd, C c) {
|
||||
// assignment patterns should not appear in the AST, but can do for malformed
|
||||
// programs; the ASTExtractor raises a ParseError in this case, other visitors
|
||||
// should just ignore them
|
||||
return visit(nd.getLeft(), c);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package com.semmle.js.extractor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.semmle.js.ast.AClass;
|
||||
import com.semmle.js.ast.AFunction;
|
||||
import com.semmle.js.ast.AFunctionExpression;
|
||||
@@ -7,6 +13,7 @@ import com.semmle.js.ast.ArrayExpression;
|
||||
import com.semmle.js.ast.ArrayPattern;
|
||||
import com.semmle.js.ast.ArrowFunctionExpression;
|
||||
import com.semmle.js.ast.AssignmentExpression;
|
||||
import com.semmle.js.ast.AssignmentPattern;
|
||||
import com.semmle.js.ast.AwaitExpression;
|
||||
import com.semmle.js.ast.BinaryExpression;
|
||||
import com.semmle.js.ast.BindExpression;
|
||||
@@ -103,6 +110,7 @@ import com.semmle.js.extractor.ExtractorConfig.Platform;
|
||||
import com.semmle.js.extractor.ExtractorConfig.SourceType;
|
||||
import com.semmle.js.extractor.ScopeManager.DeclKind;
|
||||
import com.semmle.js.extractor.ScopeManager.Scope;
|
||||
import com.semmle.js.parser.ParseError;
|
||||
import com.semmle.ts.ast.ArrayTypeExpr;
|
||||
import com.semmle.ts.ast.ConditionalTypeExpr;
|
||||
import com.semmle.ts.ast.DecoratorList;
|
||||
@@ -144,11 +152,6 @@ import com.semmle.ts.ast.UnionTypeExpr;
|
||||
import com.semmle.util.collections.CollectionUtil;
|
||||
import com.semmle.util.trap.TrapWriter;
|
||||
import com.semmle.util.trap.TrapWriter.Label;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
/** Extractor for AST-based information; invoked by the {@link JSExtractor}. */
|
||||
public class ASTExtractor {
|
||||
@@ -307,6 +310,7 @@ public class ASTExtractor {
|
||||
private final Platform platform;
|
||||
private final SourceType sourceType;
|
||||
private boolean isStrict;
|
||||
private List<ParseError> additionalErrors = new ArrayList<>();
|
||||
|
||||
public V(Platform platform, SourceType sourceType) {
|
||||
this.platform = platform;
|
||||
@@ -2054,14 +2058,22 @@ public class ASTExtractor {
|
||||
visit(nd.getRight(), key, 1, IdContext.label);
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Label visit(AssignmentPattern nd, Context c) {
|
||||
additionalErrors.add(new ParseError("Unexpected assignment pattern.", nd.getLoc().getStart()));
|
||||
return super.visit(nd, c);
|
||||
}
|
||||
}
|
||||
|
||||
public void extract(Node root, Platform platform, SourceType sourceType, int toplevelKind) {
|
||||
public List<ParseError> extract(Node root, Platform platform, SourceType sourceType, int toplevelKind) {
|
||||
lexicalExtractor.getMetrics().startPhase(ExtractionPhase.ASTExtractor_extract);
|
||||
trapwriter.addTuple("toplevels", toplevelLabel, toplevelKind);
|
||||
locationManager.emitNodeLocation(root, toplevelLabel);
|
||||
|
||||
root.accept(new V(platform, sourceType), null);
|
||||
V visitor = new V(platform, sourceType);
|
||||
root.accept(visitor, null);
|
||||
lexicalExtractor.getMetrics().stopPhase(ExtractionPhase.ASTExtractor_extract);
|
||||
return visitor.additionalErrors;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ public class JSExtractor {
|
||||
new JSDocExtractor(textualExtractor).extract(lexicalExtractor.getComments());
|
||||
lexicalExtractor.purge();
|
||||
|
||||
scriptExtractor.extract(ast, platform, sourceType, toplevelKind);
|
||||
parserRes.getErrors().addAll(scriptExtractor.extract(ast, platform, sourceType, toplevelKind));
|
||||
new CFGExtractor(scriptExtractor).extract(ast);
|
||||
} else {
|
||||
lexicalExtractor =
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Main {
|
||||
* A version identifier that should be updated every time the extractor changes in such a way that
|
||||
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
|
||||
*/
|
||||
public static final String EXTRACTOR_VERSION = "2019-11-26";
|
||||
public static final String EXTRACTOR_VERSION = "2020-01-06";
|
||||
|
||||
public static final Pattern NEWLINE = Pattern.compile("\n");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user