Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,10 @@ private void setupFilters() {
for (String extension : fileTypes.keySet()) patterns.add("**/*" + extension);

// exclude files whose name strongly suggests they are minified
patterns.add("-**/*.min.js");
patterns.add("-**/*-min.js");
if (!EnvironmentVariables.allowMinifiedFiles()) {
patterns.add("-**/*.min.js");
patterns.add("-**/*-min.js");
}

// exclude `node_modules` and `bower_components`
patterns.add("-**/node_modules");
Expand Down Expand Up @@ -1074,6 +1076,7 @@ private ExtractorConfig mkExtractorConfig() {
config = config.withSourceType(getSourceType());
config = config.withVirtualSourceRoot(virtualSourceRoot);
if (defaultEncoding != null) config = config.withDefaultEncoding(defaultEncoding);
config = config.withAllowMinified(EnvironmentVariables.allowMinifiedFiles());
return config;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,12 @@ public static String getWipDatabase() {
public static boolean isActionsExtractor() {
return Env.systemEnv().getNonEmpty(CODEQL_EXTRACTOR_ACTIONS_WIP_DATABASE_ENV_VAR) != null;
}

public static boolean allowMinifiedFiles() {
String env = Env.systemEnv().getNonEmpty("CODEQL_EXTRACTOR_JAVASCRIPT_ALLOW_MINIFIED_FILES");
if (env == null) {
return false; // default is to not allow minified files
}
return Boolean.parseBoolean(env);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ public Set<String> getPredefinedGlobals() {
/** Should parse errors be reported as violations instead of aborting extraction? */
private boolean tolerateParseErrors;

/** Should minified files be allowed? */
private boolean allowMinified;

/** How should HTML files be extracted? */
private HtmlPopulator.Config htmlHandling;

Expand Down Expand Up @@ -236,6 +239,7 @@ public ExtractorConfig(boolean experimental) {
this.sourceType = SourceType.AUTO;
this.htmlHandling = HtmlPopulator.Config.ELEMENTS;
this.tolerateParseErrors = true;
this.allowMinified = false;
if (experimental) {
this.mozExtensions = true;
this.jscript = true;
Expand All @@ -258,6 +262,7 @@ public ExtractorConfig(ExtractorConfig that) {
this.v8Extensions = that.v8Extensions;
this.e4x = that.e4x;
this.tolerateParseErrors = that.tolerateParseErrors;
this.allowMinified = that.allowMinified;
this.fileType = that.fileType;
this.sourceType = that.sourceType;
this.htmlHandling = that.htmlHandling;
Expand Down Expand Up @@ -357,6 +362,16 @@ public ExtractorConfig withTolerateParseErrors(boolean tolerateParseErrors) {
return res;
}

public boolean isAllowMinified() {
return allowMinified;
}

public ExtractorConfig withAllowMinified(boolean allowMinified) {
ExtractorConfig res = new ExtractorConfig(this);
res.allowMinified = allowMinified;
return res;
}

public boolean hasFileType() {
return fileType != null;
}
Expand Down Expand Up @@ -467,6 +482,8 @@ public String toString() {
+ e4x
+ ", tolerateParseErrors="
+ tolerateParseErrors
+ ", allowMinified="
+ allowMinified
+ ", htmlHandling="
+ htmlHandling
+ ", fileType="
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,10 +549,15 @@ private ParseResultInfo extractContents(
new TextualExtractor(
trapwriter, locationManager, source, config.getExtractLines(), metrics, extractedFile);
ParseResultInfo loc = extractor.extract(textualExtractor);
int numLines = textualExtractor.isSnippet() ? 0 : textualExtractor.getNumLines();
int linesOfCode = loc.getLinesOfCode(), linesOfComments = loc.getLinesOfComments();
trapwriter.addTuple("numlines", fileLabel, numLines, linesOfCode, linesOfComments);
trapwriter.addTuple("filetype", fileLabel, fileType.toString());
if (loc.getSkipReason() != null) {
System.err.println("Skipping file " + extractedFile + ": " + loc.getSkipReason());
System.err.flush();
} else{
int numLines = textualExtractor.isSnippet() ? 0 : textualExtractor.getNumLines();
int linesOfCode = loc.getLinesOfCode(), linesOfComments = loc.getLinesOfComments();
trapwriter.addTuple("numlines", fileLabel, numLines, linesOfCode, linesOfComments);
trapwriter.addTuple("filetype", fileLabel, fileType.toString());
}
metrics.stopPhase(ExtractionPhase.FileExtractor_extractContents);
metrics.writeTimingsToTrap(trapwriter);
successful = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,27 @@
public class ParseResultInfo {
private int linesOfCode, linesOfComments;
private List<ParseError> parseErrors;
private String skipReason;

public ParseResultInfo(int linesOfCode, int linesOfComments, List<ParseError> parseErrors) {
this.linesOfCode = linesOfCode;
this.linesOfComments = linesOfComments;
this.parseErrors = new ArrayList<>(parseErrors);
}

private ParseResultInfo() {
this.linesOfCode = 0;
this.linesOfComments = 0;
this.parseErrors = new ArrayList<>();
this.skipReason = null;
}

public static final ParseResultInfo skipped(String reason) {
ParseResultInfo info = new ParseResultInfo();
info.skipReason = reason;
return info;
}

public void add(ParseResultInfo that) {
this.linesOfCode += that.linesOfCode;
this.linesOfComments += that.linesOfComments;
Expand All @@ -41,4 +55,11 @@ public int getLinesOfComments() {
public List<ParseError> getParseErrors() {
return parseErrors;
}

/**
* If extraction of this file was skipped, gets the reason for skipping it.
*/
public String getSkipReason() {
return skipReason;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,34 @@ private boolean isAlwaysCommonJSModule(String extension, String packageType) {
return extension.equals(".cjs") || (extension.equals(".js") && "commonjs".equals(packageType));
}

private boolean isMinified(String source) {
// If the average line length is over 200 characters, consider the file minified.
int numberOfLineBreaks = 0;
for (int i = 0; i < source.length(); i++) {
char c = source.charAt(i);
if (c == '\n') {
numberOfLineBreaks++;
} else if (c == '\r') {
numberOfLineBreaks++;
if (i + 1 < source.length() && source.charAt(i + 1) == '\n') {
i++; // skip the next \n in case of \r\n
}
}
}
int averageLineLength =
numberOfLineBreaks == 0 ? source.length() : source.length() / numberOfLineBreaks;
return averageLineLength > 200;
}

@Override
public ParseResultInfo extract(TextualExtractor textualExtractor) {
LocationManager locationManager = textualExtractor.getLocationManager();
String source = textualExtractor.getSource();

if (!config.isAllowMinified() && isMinified(source)) {
return ParseResultInfo.skipped("File appears to be minified.");
}

String shebangLine = null, shebangLineTerm = null;

if (source.startsWith("#!")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: majorAnalysis
---
* JavaScript files with an average line length greater than 200 are now considered minified and will no longer be analyzed.
For use-cases where minified files should be analyzed, the orginal behaviour can be restored by setting the environment variable
`CODEQL_EXTRACTOR_JAVASCRIPT_ALLOW_MINIFIED_FILES=true`.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
| jquery-datatables.js:0:0:0:0 | jquery-datatables.js | library |
| jquery-jstree.js:0:0:0:0 | jquery-jstree.js | library |
| jquery-snippet.js:0:0:0:0 | jquery-snippet.js | library |
| json-like.js:0:0:0:0 | json-like.js | generated |
| jsx-old.js:0:0:0:0 | jsx-old.js | generated |
| jsx.js:0:0:0:0 | jsx.js | generated |
| multi-part-bundle.html:0:0:0:0 | multi-part-bundle.html | generated |
Expand Down
Loading