Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions javascript/ql/lib/semmle/javascript/AST.qll
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class AstNode extends @ast_node, NodeInStmtContainer {

/** Gets the first token belonging to this element. */
Token getFirstToken() {
exists(DbLocation l1, DbLocation l2, string filepath, int startline, int startcolumn |
exists(Location l1, Location l2, string filepath, int startline, int startcolumn |
l1 = this.getLocation() and
l2 = result.getLocation() and
l1.hasLocationInfo(filepath, startline, startcolumn, _, _) and
Expand All @@ -41,7 +41,7 @@ class AstNode extends @ast_node, NodeInStmtContainer {

/** Gets the last token belonging to this element. */
Token getLastToken() {
exists(DbLocation l1, DbLocation l2, string filepath, int endline, int endcolumn |
exists(Location l1, Location l2, string filepath, int endline, int endcolumn |
l1 = this.getLocation() and
l2 = result.getLocation() and
l1.hasLocationInfo(filepath, _, _, endline, endcolumn) and
Expand Down
3 changes: 1 addition & 2 deletions javascript/ql/lib/semmle/javascript/Files.qll
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import javascript
private import NodeModuleResolutionImpl
private import codeql.util.FileSystem
private import internal.Locations

private module FsInput implements InputSig {
abstract class ContainerBase extends @container {
Expand Down Expand Up @@ -99,7 +98,7 @@ class File extends Container, Impl::File {
*
* Note that files have special locations starting and ending at line zero, column zero.
*/
DbLocation getLocation() { result = getLocatableLocation(this) }
Location getLocation() { hasLocation(this, result) }

/** Gets the number of lines in this file. */
int getNumberOfLines() { result = sum(int loc | numlines(this, loc, _, _) | loc) }
Expand Down
3 changes: 1 addition & 2 deletions javascript/ql/lib/semmle/javascript/JSON.qll
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/

import javascript
private import semmle.javascript.internal.Locations

/**
* A JSON-encoded value, which may be a primitive value, an array or an object.
Expand Down Expand Up @@ -33,7 +32,7 @@ class JsonValue extends @json_value, Locatable {
override string toString() { json(this, _, _, _, result) }

/** Gets the JSON file containing this value. */
File getJsonFile() { result = getLocatableLocation(this).getFile() }
File getJsonFile() { exists(Location loc | json_locations(this, loc) and result = loc.getFile()) }

/** If this is an object, gets the value of property `name`. */
JsonValue getPropValue(string name) { json_properties(this, name, result) }
Expand Down
50 changes: 30 additions & 20 deletions javascript/ql/lib/semmle/javascript/Locations.qll
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/** Provides classes for working with locations and program elements that have locations. */

import javascript
private import internal.Locations

/**
* A location as given by a file, a start line, a start column,
Expand All @@ -11,31 +10,31 @@ private import internal.Locations
*
* For more information about locations see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
class DbLocation extends TDbLocation {
final class Location extends @location_default {
/** Gets the file for this location. */
File getFile() { dbLocationInfo(this, result, _, _, _, _) }
File getFile() { locations_default(this, result, _, _, _, _) }

/** Gets the 1-based line number (inclusive) where this location starts. */
int getStartLine() { dbLocationInfo(this, _, result, _, _, _) }
int getStartLine() { locations_default(this, _, result, _, _, _) }

/** Gets the 1-based column number (inclusive) where this location starts. */
int getStartColumn() { dbLocationInfo(this, _, _, result, _, _) }
int getStartColumn() { locations_default(this, _, _, result, _, _) }

/** Gets the 1-based line number (inclusive) where this location ends. */
int getEndLine() { dbLocationInfo(this, _, _, _, result, _) }
int getEndLine() { locations_default(this, _, _, _, result, _) }

/** Gets the 1-based column number (inclusive) where this location ends. */
int getEndColumn() { dbLocationInfo(this, _, _, _, _, result) }
int getEndColumn() { locations_default(this, _, _, _, _, result) }

/** Gets the number of lines covered by this location. */
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }

/** Holds if this location starts before location `that`. */
pragma[inline]
predicate startsBefore(DbLocation that) {
exists(File f, int sl1, int sc1, int sl2, int sc2 |
dbLocationInfo(this, f, sl1, sc1, _, _) and
dbLocationInfo(that, f, sl2, sc2, _, _)
predicate startsBefore(Location that) {
exists(string f, int sl1, int sc1, int sl2, int sc2 |
this.hasLocationInfo(f, sl1, sc1, _, _) and
that.hasLocationInfo(f, sl2, sc2, _, _)
|
sl1 < sl2
or
Expand All @@ -45,10 +44,10 @@ class DbLocation extends TDbLocation {

/** Holds if this location ends after location `that`. */
pragma[inline]
predicate endsAfter(DbLocation that) {
exists(File f, int el1, int ec1, int el2, int ec2 |
dbLocationInfo(this, f, _, _, el1, ec1) and
dbLocationInfo(that, f, _, _, el2, ec2)
predicate endsAfter(Location that) {
exists(string f, int el1, int ec1, int el2, int ec2 |
this.hasLocationInfo(f, _, _, el1, ec1) and
that.hasLocationInfo(f, _, _, el2, ec2)
|
el1 > el2
or
Expand All @@ -60,10 +59,10 @@ class DbLocation extends TDbLocation {
* Holds if this location contains location `that`, meaning that it starts
* before and ends after it.
*/
predicate contains(DbLocation that) { this.startsBefore(that) and this.endsAfter(that) }
predicate contains(Location that) { this.startsBefore(that) and this.endsAfter(that) }

/** Holds if this location is empty. */
predicate isEmpty() { exists(int l, int c | dbLocationInfo(this, _, l, c, l, c - 1)) }
predicate isEmpty() { exists(int l, int c | this.hasLocationInfo(_, l, c, l, c - 1)) }

/** Gets a textual representation of this element. */
string toString() { result = this.getFile().getBaseName() + ":" + this.getStartLine().toString() }
Expand All @@ -79,21 +78,27 @@ class DbLocation extends TDbLocation {
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(File f |
dbLocationInfo(this, f, startline, startcolumn, endline, endcolumn) and
locations_default(this, f, startline, startcolumn, endline, endcolumn) and
filepath = f.getAbsolutePath()
)
}
}

final class Location = LocationImpl;
cached
private Location getLocatableLocation(@locatable l) {
hasLocation(l, result) or
xmllocations(l, result) or
json_locations(l, result) or
yaml_locations(l, result)
}

/** A program element with a location. */
class Locatable extends @locatable {
/** Gets the file this program element comes from. */
File getFile() { result = this.getLocation().getFile() }

/** Gets this element's location. */
final DbLocation getLocation() { result = getLocatableLocation(this) }
final Location getLocation() { result = getLocatableLocation(this) }

/**
* Gets the line on which this element starts.
Expand Down Expand Up @@ -144,3 +149,8 @@ class Locatable extends @locatable {
*/
string getAPrimaryQlClass() { result = "???" }
}

/**
* DEPRECATED. Use `Location` instead.
*/
deprecated class DbLocation = Location;
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class FirstLineOf extends Locatable {
then endcolumn = xc
else
endcolumn =
max(int c | any(DbLocation l).hasLocationInfo(filepath, startline, _, startline, c))
max(int c | any(Location l).hasLocationInfo(filepath, startline, _, startline, c))
)
}
}
Expand Down
83 changes: 29 additions & 54 deletions javascript/ql/lib/semmle/javascript/SSA.qll
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ private module Internal {
*/
cached
newtype TSsaDefinition =
TExplicitDef(ReachableBasicBlock bb, int i, VarDef d, SsaSourceVariable v) {
bb.defAt(i, v, d) and
TExplicitDef(ReachableBasicBlock bb, int i, VarDef d, SsaSourceVariable v, VarRef lhs) {
bb.defAt(i, v, d, lhs) and
(
liveAfterDef(bb, i, v) or
v.isCaptured()
Expand Down Expand Up @@ -412,17 +412,22 @@ class SsaVariable extends TSsaDefinition {
/** Gets a textual representation of this element. */
string toString() { result = this.getDefinition().prettyPrintRef() }

/** Gets the location of this SSA variable. */
Location getLocation() { result = this.getDefinition().getLocation() }

/**
* DEPRECATED. Use `getLocation().hasLocationInfo()` instead.
*
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
deprecated predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getDefinition().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}

Expand Down Expand Up @@ -478,23 +483,22 @@ class SsaDefinition extends TSsaDefinition {
string toString() { result = this.prettyPrintDef() }

/**
* DEPRECATED. Use `getLocation().hasLocationInfo()` instead.
*
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
abstract predicate hasLocationInfo(
deprecated predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}

/** Gets the location of this element. */
final Location getLocation() {
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
result.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
)
}
Location getLocation() { result = this.getBasicBlock().getLocation() }

/** Gets the function or toplevel to which this definition belongs. */
StmtContainer getContainer() { result = this.getBasicBlock().getContainer() }
Expand All @@ -505,36 +509,34 @@ class SsaDefinition extends TSsaDefinition {
*/
class SsaExplicitDefinition extends SsaDefinition, TExplicitDef {
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
this = TExplicitDef(bb, i, _, v)
this = TExplicitDef(bb, i, _, v, _)
}

/** This SSA definition corresponds to the definition of `v` at `def`. */
predicate defines(VarDef def, SsaSourceVariable v) { this = TExplicitDef(_, _, def, v) }
predicate defines(VarDef def, SsaSourceVariable v) { this = TExplicitDef(_, _, def, v, _) }

/** Gets the variable definition wrapped by this SSA definition. */
VarDef getDef() { this = TExplicitDef(_, _, result, _) }
VarDef getDef() { this = TExplicitDef(_, _, result, _, _) }

/** Gets the variable reference appearing on the left-hand side of this assignment. */
VarRef getLhs() { this = TExplicitDef(_, _, _, _, result) }

/** Gets the basic block to which this definition belongs. */
override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }

override SsaSourceVariable getSourceVariable() { this = TExplicitDef(_, _, _, result) }
override SsaSourceVariable getSourceVariable() { this = TExplicitDef(_, _, _, result, _) }

override VarDef getAContributingVarDef() { result = this.getDef() }

override string prettyPrintRef() {
exists(int l, int c | this.hasLocationInfo(_, l, c, _, _) | result = "def@" + l + ":" + c)
exists(int l, int c | this.getLocation().hasLocationInfo(_, l, c, _, _) |
result = "def@" + l + ":" + c
)
}

override string prettyPrintDef() { result = this.getDef().toString() }

override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(Location loc |
pragma[only_bind_into](loc) = pragma[only_bind_into](this.getDef()).getLocation() and
loc.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
)
}
override Location getLocation() { result = this.getLhs().getLocation() }

/**
* Gets the data flow node representing the incoming value assigned at this definition,
Expand All @@ -557,21 +559,10 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
abstract string getKind();

override string prettyPrintRef() {
exists(int l, int c | this.hasLocationInfo(_, l, c, _, _) |
exists(int l, int c | this.getLocation().hasLocationInfo(_, l, c, _, _) |
result = this.getKind() + "@" + l + ":" + c
)
}

override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
endline = startline and
endcolumn = startcolumn and
exists(Location loc |
pragma[only_bind_into](loc) = pragma[only_bind_into](this.getBasicBlock()).getLocation() and
loc.hasLocationInfo(filepath, startline, startcolumn, _, _)
)
}
}

/**
Expand Down Expand Up @@ -617,16 +608,6 @@ class SsaVariableCapture extends SsaImplicitDefinition, TCapture {
override string getKind() { result = "capture" }

override string prettyPrintDef() { result = "capture variable " + this.getSourceVariable() }

override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(ReachableBasicBlock bb, int i | this.definesAt(bb, i, _) |
bb.getNode(i)
.getLocation()
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
)
}
}

/**
Expand Down Expand Up @@ -747,13 +728,7 @@ class SsaRefinementNode extends SsaPseudoDefinition, TRefinement {
this.getSourceVariable() + " = refine[" + this.getGuard() + "](" + this.ppInputs() + ")"
}

override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getGuard()
.getLocation()
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
override Location getLocation() { result = this.getGuard().getLocation() }
}

module Ssa {
Expand Down
4 changes: 2 additions & 2 deletions javascript/ql/lib/semmle/javascript/Variables.qll
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,9 @@ class LocalVariable extends Variable {
* If the variable has one or more declarations, the location of the first declaration is used.
* If the variable has no declaration, the entry point of its declaring container is used.
*/
DbLocation getLocation() {
Location getLocation() {
result =
min(DbLocation loc |
min(Location loc |
loc = this.getADeclaration().getLocation()
|
loc order by loc.getStartLine(), loc.getStartColumn()
Expand Down
7 changes: 3 additions & 4 deletions javascript/ql/lib/semmle/javascript/XML.qll
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
*/

import semmle.files.FileSystem
private import semmle.javascript.internal.Locations
private import codeql.xml.Xml

private module Input implements InputSig<File, DbLocation> {
private module Input implements InputSig<File, Location> {
class XmlLocatableBase = @xmllocatable or @xmlnamespaceable;

predicate xmllocations_(XmlLocatableBase e, DbLocation loc) { loc = getLocatableLocation(e) }
predicate xmllocations_(XmlLocatableBase e, Location loc) { xmllocations(e, loc) }

class XmlParentBase = @xmlparent;

Expand Down Expand Up @@ -67,4 +66,4 @@ private module Input implements InputSig<File, DbLocation> {
}
}

import Make<File, DbLocation, Input>
import Make<File, Location, Input>
2 changes: 0 additions & 2 deletions javascript/ql/lib/semmle/javascript/YAML.qll
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import javascript
private import codeql.yaml.Yaml as LibYaml

private module YamlSig implements LibYaml::InputSig {
class Location = DbLocation;

class LocatableBase extends @yaml_locatable, Locatable { }

import javascript
Expand Down
Loading