Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f173e30

Browse files
committed
JS: Add getConstantStringParts() and HTML concat node
1 parent f101944 commit f173e30

5 files changed

Lines changed: 216 additions & 0 deletions

File tree

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

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,36 @@ module StringOps {
675675
ConcatenationLeaf getALeaf() {
676676
this = StringConcatenation::getRoot(result)
677677
}
678+
679+
/**
680+
* Returns the concatenation of all constant operands in this concatenation,
681+
* ignoring the non-constant parts entirely.
682+
*
683+
* For example, for the following concatenation
684+
* ```
685+
* `Hello ${person}, how are you?`
686+
* ```
687+
* the result is `"Hello , how are you?"`
688+
*/
689+
string getConstantStringParts() {
690+
result = getStringValue()
691+
or
692+
not exists(getStringValue()) and
693+
result = strictconcat(StringLiteralLike leaf |
694+
leaf = getALeaf().asExpr()
695+
|
696+
leaf.getStringValue()
697+
order by leaf.getFirstToken().getIndex() asc
698+
)
699+
}
700+
}
701+
702+
/** A string literal or template literal without any substitutions. */
703+
private class StringLiteralLike extends Expr {
704+
StringLiteralLike() {
705+
this instanceof StringLiteral or
706+
this instanceof TemplateElement
707+
}
678708
}
679709

680710
/**
@@ -694,4 +724,33 @@ module StringOps {
694724
isLeaf()
695725
}
696726
}
727+
728+
/**
729+
* The root node in a concatenation of one or more strings contain HTML fragments.
730+
*/
731+
class HtmlConcatenationRoot extends ConcatenationRoot {
732+
pragma[noinline]
733+
HtmlConcatenationRoot() {
734+
getConstantStringParts().regexpMatch("(?s).*</?[a-zA-Z][^\\r\\n<>/]*/?>.*")
735+
}
736+
}
737+
738+
/**
739+
* A data flow node that is part of an HTML string concatenation.
740+
*/
741+
class HtmlConcatenationNode extends ConcatenationNode {
742+
HtmlConcatenationNode() {
743+
getRoot() instanceof HtmlConcatenationRoot
744+
}
745+
}
746+
747+
/**
748+
* A data flow node that is part of an HTML string concatenation,
749+
* and is not itself a concatenation operator.
750+
*/
751+
class HtmlConcatenationLeaf extends ConcatenationLeaf {
752+
HtmlConcatenationLeaf() {
753+
getRoot() instanceof HtmlConcatenationRoot
754+
}
755+
}
697756
}

javascript/ql/src/semmle/javascript/Templates.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ class TemplateLiteral extends Expr, @templateliteral {
4242
*/
4343
Expr getAnElement() { result = getElement(_) }
4444

45+
/**
46+
* Gets the number of elements of this template literal.
47+
*/
48+
int getNumElement() { result = count(getAnElement()) }
49+
4550
override predicate isImpure() { getAnElement().isImpure() }
4651

4752
override string getStringValue() {

javascript/ql/test/library-tests/StringConcatenation/StringOps.expected

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@ concatenation
22
| closure.js:5:1:5:37 | build(' ... 'four') |
33
| closure.js:5:1:5:46 | build(' ... 'five' |
44
| closure.js:5:14:5:28 | 'two' + 'three' |
5+
| html-concat.js:2:14:2:26 | `<b>${x}</b>` |
6+
| html-concat.js:3:14:3:26 | `<B>${x}</B>` |
7+
| html-concat.js:5:21:5:47 | `Hey <s ... trong>` |
8+
| html-concat.js:7:18:10:24 | `\\n H ... m!</i>` |
9+
| html-concat.js:13:3:13:18 | buffer |
10+
| html-concat.js:13:3:13:18 | buffer += '<li>' |
11+
| html-concat.js:14:3:14:13 | buffer |
12+
| html-concat.js:14:3:14:13 | buffer += x |
13+
| html-concat.js:15:3:15:15 | buffer |
14+
| html-concat.js:15:3:15:15 | buffer += '!' |
515
| tst.js:3:3:3:12 | x |
616
| tst.js:3:3:3:12 | x += "two" |
717
| tst.js:4:3:4:14 | x |
@@ -43,6 +53,24 @@ concatenationOperand
4353
| closure.js:5:22:5:28 | 'three' |
4454
| closure.js:5:31:5:36 | 'four' |
4555
| closure.js:5:41:5:46 | 'five' |
56+
| html-concat.js:2:15:2:17 | <b> |
57+
| html-concat.js:2:20:2:20 | x |
58+
| html-concat.js:2:22:2:25 | </b> |
59+
| html-concat.js:3:15:3:17 | <B> |
60+
| html-concat.js:3:20:3:20 | x |
61+
| html-concat.js:3:22:3:25 | </B> |
62+
| html-concat.js:5:22:5:33 | Hey <strong> |
63+
| html-concat.js:5:36:5:36 | x |
64+
| html-concat.js:5:38:5:46 | </strong> |
65+
| html-concat.js:7:19:8:10 | \\n Hello |
66+
| html-concat.js:8:13:8:13 | x |
67+
| html-concat.js:8:15:10:23 | .\\n \\n ... um!</i> |
68+
| html-concat.js:13:3:13:8 | buffer |
69+
| html-concat.js:13:13:13:18 | '<li>' |
70+
| html-concat.js:14:3:14:8 | buffer |
71+
| html-concat.js:14:13:14:13 | x |
72+
| html-concat.js:15:3:15:8 | buffer |
73+
| html-concat.js:15:13:15:15 | '!' |
4674
| tst.js:3:3:3:3 | x |
4775
| tst.js:3:8:3:12 | "two" |
4876
| tst.js:4:3:4:3 | x |
@@ -101,6 +129,24 @@ concatenationLeaf
101129
| closure.js:5:22:5:28 | 'three' |
102130
| closure.js:5:31:5:36 | 'four' |
103131
| closure.js:5:41:5:46 | 'five' |
132+
| html-concat.js:2:15:2:17 | <b> |
133+
| html-concat.js:2:20:2:20 | x |
134+
| html-concat.js:2:22:2:25 | </b> |
135+
| html-concat.js:3:15:3:17 | <B> |
136+
| html-concat.js:3:20:3:20 | x |
137+
| html-concat.js:3:22:3:25 | </B> |
138+
| html-concat.js:5:22:5:33 | Hey <strong> |
139+
| html-concat.js:5:36:5:36 | x |
140+
| html-concat.js:5:38:5:46 | </strong> |
141+
| html-concat.js:7:19:8:10 | \\n Hello |
142+
| html-concat.js:8:13:8:13 | x |
143+
| html-concat.js:8:15:10:23 | .\\n \\n ... um!</i> |
144+
| html-concat.js:13:3:13:8 | buffer |
145+
| html-concat.js:13:13:13:18 | '<li>' |
146+
| html-concat.js:14:3:14:8 | buffer |
147+
| html-concat.js:14:13:14:13 | x |
148+
| html-concat.js:15:3:15:8 | buffer |
149+
| html-concat.js:15:13:15:15 | '!' |
104150
| tst.js:3:3:3:3 | x |
105151
| tst.js:3:8:3:12 | "two" |
106152
| tst.js:4:3:4:3 | x |
@@ -155,6 +201,34 @@ concatenationNode
155201
| closure.js:5:22:5:28 | 'three' |
156202
| closure.js:5:31:5:36 | 'four' |
157203
| closure.js:5:41:5:46 | 'five' |
204+
| html-concat.js:2:14:2:26 | `<b>${x}</b>` |
205+
| html-concat.js:2:15:2:17 | <b> |
206+
| html-concat.js:2:20:2:20 | x |
207+
| html-concat.js:2:22:2:25 | </b> |
208+
| html-concat.js:3:14:3:26 | `<B>${x}</B>` |
209+
| html-concat.js:3:15:3:17 | <B> |
210+
| html-concat.js:3:20:3:20 | x |
211+
| html-concat.js:3:22:3:25 | </B> |
212+
| html-concat.js:5:21:5:47 | `Hey <s ... trong>` |
213+
| html-concat.js:5:22:5:33 | Hey <strong> |
214+
| html-concat.js:5:36:5:36 | x |
215+
| html-concat.js:5:38:5:46 | </strong> |
216+
| html-concat.js:7:18:10:24 | `\\n H ... m!</i>` |
217+
| html-concat.js:7:19:8:10 | \\n Hello |
218+
| html-concat.js:8:13:8:13 | x |
219+
| html-concat.js:8:15:10:23 | .\\n \\n ... um!</i> |
220+
| html-concat.js:13:3:13:8 | buffer |
221+
| html-concat.js:13:3:13:18 | buffer |
222+
| html-concat.js:13:3:13:18 | buffer += '<li>' |
223+
| html-concat.js:13:13:13:18 | '<li>' |
224+
| html-concat.js:14:3:14:8 | buffer |
225+
| html-concat.js:14:3:14:13 | buffer |
226+
| html-concat.js:14:3:14:13 | buffer += x |
227+
| html-concat.js:14:13:14:13 | x |
228+
| html-concat.js:15:3:15:8 | buffer |
229+
| html-concat.js:15:3:15:15 | buffer |
230+
| html-concat.js:15:3:15:15 | buffer += '!' |
231+
| html-concat.js:15:13:15:15 | '!' |
158232
| tst.js:3:3:3:3 | x |
159233
| tst.js:3:3:3:12 | x |
160234
| tst.js:3:3:3:12 | x += "two" |
@@ -241,6 +315,30 @@ operand
241315
| closure.js:5:1:5:46 | build(' ... 'five' | 1 | closure.js:5:41:5:46 | 'five' |
242316
| closure.js:5:14:5:28 | 'two' + 'three' | 0 | closure.js:5:14:5:18 | 'two' |
243317
| closure.js:5:14:5:28 | 'two' + 'three' | 1 | closure.js:5:22:5:28 | 'three' |
318+
| html-concat.js:2:14:2:26 | `<b>${x}</b>` | 0 | html-concat.js:2:15:2:17 | <b> |
319+
| html-concat.js:2:14:2:26 | `<b>${x}</b>` | 1 | html-concat.js:2:20:2:20 | x |
320+
| html-concat.js:2:14:2:26 | `<b>${x}</b>` | 2 | html-concat.js:2:22:2:25 | </b> |
321+
| html-concat.js:3:14:3:26 | `<B>${x}</B>` | 0 | html-concat.js:3:15:3:17 | <B> |
322+
| html-concat.js:3:14:3:26 | `<B>${x}</B>` | 1 | html-concat.js:3:20:3:20 | x |
323+
| html-concat.js:3:14:3:26 | `<B>${x}</B>` | 2 | html-concat.js:3:22:3:25 | </B> |
324+
| html-concat.js:5:21:5:47 | `Hey <s ... trong>` | 0 | html-concat.js:5:22:5:33 | Hey <strong> |
325+
| html-concat.js:5:21:5:47 | `Hey <s ... trong>` | 1 | html-concat.js:5:36:5:36 | x |
326+
| html-concat.js:5:21:5:47 | `Hey <s ... trong>` | 2 | html-concat.js:5:38:5:46 | </strong> |
327+
| html-concat.js:7:18:10:24 | `\\n H ... m!</i>` | 0 | html-concat.js:7:19:8:10 | \\n Hello |
328+
| html-concat.js:7:18:10:24 | `\\n H ... m!</i>` | 1 | html-concat.js:8:13:8:13 | x |
329+
| html-concat.js:7:18:10:24 | `\\n H ... m!</i>` | 2 | html-concat.js:8:15:10:23 | .\\n \\n ... um!</i> |
330+
| html-concat.js:13:3:13:18 | buffer | 0 | html-concat.js:13:3:13:8 | buffer |
331+
| html-concat.js:13:3:13:18 | buffer | 1 | html-concat.js:13:13:13:18 | '<li>' |
332+
| html-concat.js:13:3:13:18 | buffer += '<li>' | 0 | html-concat.js:13:3:13:8 | buffer |
333+
| html-concat.js:13:3:13:18 | buffer += '<li>' | 1 | html-concat.js:13:13:13:18 | '<li>' |
334+
| html-concat.js:14:3:14:13 | buffer | 0 | html-concat.js:14:3:14:8 | buffer |
335+
| html-concat.js:14:3:14:13 | buffer | 1 | html-concat.js:14:13:14:13 | x |
336+
| html-concat.js:14:3:14:13 | buffer += x | 0 | html-concat.js:14:3:14:8 | buffer |
337+
| html-concat.js:14:3:14:13 | buffer += x | 1 | html-concat.js:14:13:14:13 | x |
338+
| html-concat.js:15:3:15:15 | buffer | 0 | html-concat.js:15:3:15:8 | buffer |
339+
| html-concat.js:15:3:15:15 | buffer | 1 | html-concat.js:15:13:15:15 | '!' |
340+
| html-concat.js:15:3:15:15 | buffer += '!' | 0 | html-concat.js:15:3:15:8 | buffer |
341+
| html-concat.js:15:3:15:15 | buffer += '!' | 1 | html-concat.js:15:13:15:15 | '!' |
244342
| tst.js:3:3:3:12 | x | 0 | tst.js:3:3:3:3 | x |
245343
| tst.js:3:3:3:12 | x | 1 | tst.js:3:8:3:12 | "two" |
246344
| tst.js:3:3:3:12 | x += "two" | 0 | tst.js:3:3:3:3 | x |
@@ -314,6 +412,17 @@ nextLeaf
314412
| closure.js:5:14:5:18 | 'two' | closure.js:5:22:5:28 | 'three' |
315413
| closure.js:5:22:5:28 | 'three' | closure.js:5:31:5:36 | 'four' |
316414
| closure.js:5:31:5:36 | 'four' | closure.js:5:41:5:46 | 'five' |
415+
| html-concat.js:2:15:2:17 | <b> | html-concat.js:2:20:2:20 | x |
416+
| html-concat.js:2:20:2:20 | x | html-concat.js:2:22:2:25 | </b> |
417+
| html-concat.js:3:15:3:17 | <B> | html-concat.js:3:20:3:20 | x |
418+
| html-concat.js:3:20:3:20 | x | html-concat.js:3:22:3:25 | </B> |
419+
| html-concat.js:5:22:5:33 | Hey <strong> | html-concat.js:5:36:5:36 | x |
420+
| html-concat.js:5:36:5:36 | x | html-concat.js:5:38:5:46 | </strong> |
421+
| html-concat.js:7:19:8:10 | \\n Hello | html-concat.js:8:13:8:13 | x |
422+
| html-concat.js:8:13:8:13 | x | html-concat.js:8:15:10:23 | .\\n \\n ... um!</i> |
423+
| html-concat.js:13:3:13:8 | buffer | html-concat.js:13:13:13:18 | '<li>' |
424+
| html-concat.js:14:3:14:8 | buffer | html-concat.js:14:13:14:13 | x |
425+
| html-concat.js:15:3:15:8 | buffer | html-concat.js:15:13:15:15 | '!' |
317426
| tst.js:3:3:3:3 | x | tst.js:3:8:3:12 | "two" |
318427
| tst.js:4:3:4:3 | x | tst.js:4:8:4:14 | "three" |
319428
| tst.js:5:3:5:3 | x | tst.js:5:8:5:13 | "four" |
@@ -341,3 +450,25 @@ nextLeaf
341450
| tst.js:61:27:61:27 | x | tst.js:61:29:61:33 | last |
342451
| tst.js:87:5:87:5 | x | tst.js:87:10:87:14 | 'two' |
343452
| tst.js:89:3:89:3 | x | tst.js:89:8:89:14 | 'three' |
453+
htmlRoot
454+
| html-concat.js:2:14:2:26 | `<b>${x}</b>` |
455+
| html-concat.js:3:14:3:26 | `<B>${x}</B>` |
456+
| html-concat.js:5:21:5:47 | `Hey <s ... trong>` |
457+
| html-concat.js:7:18:10:24 | `\\n H ... m!</i>` |
458+
| html-concat.js:13:3:13:18 | buffer |
459+
| html-concat.js:13:3:13:18 | buffer += '<li>' |
460+
htmlLeaf
461+
| html-concat.js:2:15:2:17 | <b> |
462+
| html-concat.js:2:20:2:20 | x |
463+
| html-concat.js:2:22:2:25 | </b> |
464+
| html-concat.js:3:15:3:17 | <B> |
465+
| html-concat.js:3:20:3:20 | x |
466+
| html-concat.js:3:22:3:25 | </B> |
467+
| html-concat.js:5:22:5:33 | Hey <strong> |
468+
| html-concat.js:5:36:5:36 | x |
469+
| html-concat.js:5:38:5:46 | </strong> |
470+
| html-concat.js:7:19:8:10 | \\n Hello |
471+
| html-concat.js:8:13:8:13 | x |
472+
| html-concat.js:8:15:10:23 | .\\n \\n ... um!</i> |
473+
| html-concat.js:13:3:13:8 | buffer |
474+
| html-concat.js:13:13:13:18 | '<li>' |

javascript/ql/test/library-tests/StringConcatenation/StringOps.ql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ query predicate operand(StringOps::ConcatenationNode node, int i, DataFlow::Node
1212
query predicate nextLeaf(StringOps::ConcatenationNode node, DataFlow::Node next) {
1313
next = node.getNextLeaf()
1414
}
15+
16+
query StringOps::HtmlConcatenationRoot htmlRoot() { any() }
17+
query StringOps::HtmlConcatenationLeaf htmlLeaf() { any() }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
function f(x, y) {
2+
let bold = `<b>${x}</b>`;
3+
let Bold = `<B>${x}</B>`;
4+
5+
let longTagName = `Hey <strong>${x}</strong>`;
6+
7+
let longText = `
8+
Hello ${x}.
9+
10+
<i>Lorem ipsum!</i>`;
11+
12+
let buffer = '';
13+
buffer += '<li>';
14+
buffer += x;
15+
buffer += '!';
16+
17+
return buffer;
18+
}

0 commit comments

Comments
 (0)