Skip to content

Commit a6d2ecd

Browse files
author
Stephan Brandauer
committed
review comments
1 parent 9c3fcb6 commit a6d2ecd

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,39 @@ private module HandlebarsTaintSteps {
4747
exists(DataFlow::TypeTracker t2 | result = compiledTemplate(t2, compileCall).track(t2, t))
4848
}
4949

50-
private predicate isHelperParam(
51-
string helperName, DataFlow::FunctionNode helperFunction, DataFlow::ParameterNode param,
50+
/**
51+
* Gets a reference to a parameter of a registered Handlebars helper.
52+
*
53+
* ```javascript
54+
* function loudHelper(text) {
55+
* return text.toUpperCase();
56+
* }
57+
*
58+
* hb.registerHelper("loud", loudHelper);
59+
* ```
60+
* In this example, `getRegisteredHelperParameter("loud", func, 0)` will bind `func` to
61+
* the `FunctionNode` representing `function loudHelper`, and return its parameter `text`.
62+
*/
63+
private DataFlow::ParameterNode getRegisteredHelperParam(
64+
string helperName, DataFlow::FunctionNode helperFunction,
5265
int paramIndex
5366
) {
5467
exists(DataFlow::CallNode registerHelperCall |
55-
registerHelperCall = any(Handlebars::Handlebars hb).getAMethodCall("registerHelper") and
68+
registerHelperCall = any(Handlebars::Handlebars hb).getAMemberCall("registerHelper") and
5669
registerHelperCall.getArgument(0).mayHaveStringValue(helperName) and
5770
helperFunction = registerHelperCall.getArgument(1).getAFunctionValue() and
58-
param = helperFunction.getParameter(paramIndex)
71+
result = helperFunction.getParameter(paramIndex)
5972
)
6073
}
6174

62-
/** Holds if `call` is a block wrapped inside curly braces inside the template `templateText`. */
75+
/** Gets a `call` (which is a block wrapped inside curly braces inside the template) from `templateText`.
76+
*
77+
* For example, `getAHelperCallFromTemplate("Hello {{loud customer}}")` will return `"loud customer"`.
78+
*/
6379
bindingset[templateText]
64-
predicate templateHelperParamBlock(string templateText, string call) {
65-
call = templateText.regexpFind("\\{\\{[^}]+\\}\\}", _, _).regexpReplaceAll("[{}]", "").trim() and
66-
call.regexpMatch(".*\\s.*")
80+
private string getAHelperCallFromTemplate(string templateText) {
81+
result = templateText.regexpFind("\\{\\{[^}]+\\}\\}", _, _).regexpReplaceAll("[{}]", "").trim() and
82+
result.regexpMatch(".*\\s.*")
6783
}
6884

6985
/**
@@ -85,7 +101,7 @@ private module HandlebarsTaintSteps {
85101
private predicate isTemplateHelperCallArg(
86102
string templateText, string helperName, int argIdx, string argVal
87103
) {
88-
exists(string call | templateHelperParamBlock(templateText, call) |
104+
exists(string call | call = getAHelperCallFromTemplate(templateText) |
89105
helperName = call.regexpFind("[^\\s]+", 0, _) and
90106
argIdx >= 0 and
91107
argVal = call.regexpFind("[^\\s]+", argIdx + 1, _)
@@ -126,14 +142,14 @@ private module HandlebarsTaintSteps {
126142
pred =
127143
templatingCall.getAnArgument().getALocalSource().getAPropertyWrite(paramName).getRhs() and
128144
isTemplateHelperCallArg(templateText, helperName, argIdx, paramName) and
129-
isHelperParam(helperName, helperFunction, succ, argIdx)
145+
succ = getRegisteredHelperParam(helperName, helperFunction, argIdx)
130146
)
131147
or
132148
// When we don't have a string value, we can't be sure
133-
// and will assume a step.
149+
// and we assume a step to all parameters of all helpers.
134150
not exists(string s | compileCall.getArgument(0).mayHaveStringValue(s)) and
135-
pred = templatingCall.getAnArgument().getALocalSource().getAPropertyWrite().getRhs() and
136-
isHelperParam(helperName, helperFunction, succ, _)
151+
pred = templatingCall.getArgument(0).getALocalSource().getAPropertyWrite().getRhs() and
152+
succ = getRegisteredHelperParam(helperName, helperFunction, _)
137153
)
138154
)
139155
}

0 commit comments

Comments
 (0)