Skip to content

Commit e7e2910

Browse files
committed
JS: add StringOps::Concatenation
1 parent c115451 commit e7e2910

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

javascript/ql/src/semmle/javascript/StringOps.qll

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,4 +422,71 @@ module StringOps {
422422
override DataFlow::Node getSubstring() { result = getArgument(1) }
423423
}
424424
}
425+
426+
/**
427+
* A data flow node that concatenates strings and returns the result.
428+
*/
429+
class Concatenation extends DataFlow::Node {
430+
Concatenation() {
431+
exists(StringConcatenation::getAnOperand(this))
432+
}
433+
434+
/**
435+
* Gets the `n`th operand of this string concatenation.
436+
*/
437+
DataFlow::Node getOperand(int n) {
438+
result = StringConcatenation::getOperand(this, n)
439+
}
440+
441+
/**
442+
* Gets an operand of this string concatenation.
443+
*/
444+
DataFlow::Node getAnOperand() {
445+
result = StringConcatenation::getAnOperand(this)
446+
}
447+
448+
/**
449+
* Gets the number of operands of this string concatenation.
450+
*/
451+
int getNumOperand() {
452+
result = StringConcatenation::getNumOperand(this)
453+
}
454+
455+
/**
456+
* Gets the first operand of this string concatenation.
457+
*/
458+
DataFlow::Node getFirstOperand() {
459+
result = StringConcatenation::getFirstOperand(this)
460+
}
461+
462+
/**
463+
* Gets the last operand of this string concatenation
464+
*/
465+
DataFlow::Node getLastOperand() {
466+
result = StringConcatenation::getLastOperand(this)
467+
}
468+
469+
/**
470+
* Holds if this only acts as a string coercion, such as `"" + x`.
471+
*/
472+
predicate isCoercion() {
473+
StringConcatenation::isCoercion(this)
474+
}
475+
476+
/**
477+
* Holds if this is the root of a concatenation tree, that is,
478+
* it is a concatenation operator that is not itself the immediate operand to
479+
* another concatenation operator.
480+
*/
481+
predicate isRoot() {
482+
StringConcatenation::isRoot(this)
483+
}
484+
485+
/**
486+
* Gets the root of the concatenation tree in which this is an operator.
487+
*/
488+
Concatenation getRoot() {
489+
result = StringConcatenation::getRoot(this)
490+
}
491+
}
425492
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import javascript
2+
3+
// Select all expressions whose string value contains the word "two"
4+
predicate containsTwo(DataFlow::Node node) {
5+
node.getStringValue().regexpMatch(".*two.*")
6+
or
7+
containsTwo(node.getAPredecessor())
8+
or
9+
containsTwo(node.(StringOps::Concatenation).getAnOperand())
10+
}
11+
12+
from Expr e
13+
where containsTwo(e.flow())
14+
select e

0 commit comments

Comments
 (0)