mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
JS: add query js/vue/arrow-method-on-vue-instance
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------------------------|------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Arrow method on Vue instance (`js/vue/arrow-method-on-vue-instance`) | reliability, frameworks/vue | Highlights arrow functions that are used as methods on Vue instances. Results are shown on LGTM by default.|
|
||||
| Double escaping or unescaping (`js/double-escaping`) | correctness, security, external/cwe/cwe-116 | Highlights potential double escaping or unescaping of special characters, indicating a possible violation of [CWE-116](https://cwe.mitre.org/data/definitions/116.html). Results are shown on LGTM by default. |
|
||||
| Incomplete regular expression for hostnames (`js/incomplete-hostname-regexp`) | correctness, security, external/cwe/cwe-020 | Highlights hostname sanitizers that are likely to be incomplete, indicating a violation of [CWE-020](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default.|
|
||||
| Incomplete URL substring sanitization | correctness, security, external/cwe/cwe-020 | Highlights URL sanitizers that are likely to be incomplete, indicating a violation of [CWE-020](https://cwe.mitre.org/data/definitions/20.html). Results shown on LGTM by default. |
|
||||
|
||||
@@ -23,3 +23,4 @@
|
||||
+ semmlecode-javascript-queries/React/UnusedOrUndefinedStateProperty.ql: /Frameworks/React
|
||||
+ semmlecode-javascript-queries/Electron/DisablingWebSecurity.ql: /Frameworks/Electron
|
||||
+ semmlecode-javascript-queries/Electron/AllowRunningInsecureContent.ql: /Frameworks/Electron
|
||||
+ semmlecode-javascript-queries/Vue/ArrowMethodOnVueInstance.ql: /Frameworks/Vue
|
||||
|
||||
49
javascript/ql/src/Vue/ArrowMethodOnVueInstance.qhelp
Normal file
49
javascript/ql/src/Vue/ArrowMethodOnVueInstance.qhelp
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
|
||||
The Vue framework invokes the methods of a Vue instance with
|
||||
the instance as the receiver. It is however impossible to perform
|
||||
this binding of instance and receiver for arrow functions, so the
|
||||
<code>this</code> variable in an arrow function on a Vue instance may
|
||||
not have the value that the programmer expects.
|
||||
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Ensure that the methods on a Vue instance can have their receiver bound to the instance.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
|
||||
<p>
|
||||
|
||||
The following example shows two similar Vue instances, the only
|
||||
difference is how the <code>created</code> life cycle hook
|
||||
callback is defined.
|
||||
|
||||
The first Vue instance uses an arrow function as the callback.
|
||||
This means that the <code>this</code> variable will have the global
|
||||
object as its value, causing <code>this.myProperty</code> to evaluate
|
||||
to <code>undefined</code>, which may not be intended.
|
||||
|
||||
Instead, the second Vue instance uses an ordinary function as the callback,
|
||||
causing <code>this.myProperty</code> to evaluate to <code>42</code>.
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/ArrowMethodOnVueInstance.js"/>
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Vue documentation: <a href="https://vuejs.org/v2/guide/instance.html">The Vue Instance</a></li>
|
||||
</references>
|
||||
</qhelp>
|
||||
19
javascript/ql/src/Vue/ArrowMethodOnVueInstance.ql
Normal file
19
javascript/ql/src/Vue/ArrowMethodOnVueInstance.ql
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @name Arrow method on Vue instance
|
||||
* @description An arrow method on a Vue instance doesn't have its `this` variable bound to the Vue instance.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id js/vue/arrow-method-on-vue-instance
|
||||
* @tags reliability
|
||||
* frameworks/vue
|
||||
* @precision high
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
from Vue::Instance instance, DataFlow::Node def, DataFlow::FunctionNode arrow, ThisExpr dis
|
||||
where instance.getABoundFunction() = def and
|
||||
arrow.flowsTo(def) and
|
||||
arrow.asExpr() instanceof ArrowFunctionExpr and
|
||||
arrow.asExpr() = dis.getEnclosingFunction()
|
||||
select def, "The $@ of this $@ it will not be bound to the Vue instance.", dis, "`this` variable", arrow, "arrow function"
|
||||
19
javascript/ql/src/Vue/examples/ArrowMethodOnVueInstance.js
Normal file
19
javascript/ql/src/Vue/examples/ArrowMethodOnVueInstance.js
Normal file
@@ -0,0 +1,19 @@
|
||||
new Vue({
|
||||
data: {
|
||||
myProperty: 42
|
||||
},
|
||||
created: () => {
|
||||
// BAD: prints: "myProperty is: undefined"
|
||||
console.log('myProperty is: ' + this.myProperty);
|
||||
}
|
||||
});
|
||||
|
||||
new Vue({
|
||||
data: {
|
||||
myProperty: 42
|
||||
},
|
||||
created: function () {
|
||||
// GOOD: prints: "myProperty is: 1"
|
||||
console.log('myProperty is: ' + this.myProperty);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
| tst.js:4:11:4:20 | () => this | The $@ of this $@ it will not be bound to the Vue instance. | tst.js:4:17:4:20 | this | `this` variable | tst.js:4:11:4:20 | () => this | arrow function |
|
||||
| tst.js:6:6:6:15 | () => this | The $@ of this $@ it will not be bound to the Vue instance. | tst.js:6:12:6:15 | this | `this` variable | tst.js:6:6:6:15 | () => this | arrow function |
|
||||
| tst.js:7:13:7:22 | () => this | The $@ of this $@ it will not be bound to the Vue instance. | tst.js:7:19:7:22 | this | `this` variable | tst.js:7:13:7:22 | () => this | arrow function |
|
||||
| tst.js:8:13:8:22 | () => this | The $@ of this $@ it will not be bound to the Vue instance. | tst.js:8:19:8:22 | this | `this` variable | tst.js:8:13:8:22 | () => this | arrow function |
|
||||
| tst.js:11:10:11:19 | () => this | The $@ of this $@ it will not be bound to the Vue instance. | tst.js:11:16:11:19 | this | `this` variable | tst.js:11:10:11:19 | () => this | arrow function |
|
||||
@@ -0,0 +1 @@
|
||||
Vue/ArrowMethodOnVueInstance.ql
|
||||
16
javascript/ql/test/query-tests/Vue/tst.js
Normal file
16
javascript/ql/test/query-tests/Vue/tst.js
Normal file
@@ -0,0 +1,16 @@
|
||||
let Vue = require('vue');
|
||||
|
||||
new Vue( {
|
||||
created: () => this, // NOT OK
|
||||
computed: {
|
||||
x: () => this, // NOT OK
|
||||
y: { get: () => this }, // NOT OK
|
||||
z: { set: () => this } // NOT OK
|
||||
},
|
||||
methods: {
|
||||
arrow: () => this, // NOT OK
|
||||
nonArrow: function() { this; }, // OK
|
||||
arrowWithoutThis: () => 42, // OK
|
||||
arrowWithNestedThis: () => (() => this) // OK
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user