Skip to content

Commit ee60854

Browse files
committed
JS: Add support for createNamespacedHelpers
1 parent dd1e21c commit ee60854

File tree

2 files changed

+26
-9
lines changed
  • javascript/ql
    • src/semmle/javascript/frameworks
    • test/library-tests/frameworks/Vuex

2 files changed

+26
-9
lines changed

javascript/ql/src/semmle/javascript/frameworks/Vuex.qll

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,20 @@ module Vuex {
9696
*/
9797
private class MapHelperCall extends API::CallNode {
9898
string helperName;
99+
string namespace;
99100

100101
MapHelperCall() {
101-
this = vuex().getMember(helperName).getACall() and
102-
helperName = ["mapActions", "mapGetters", "mapMutations", "mapState"]
102+
helperName = ["mapActions", "mapGetters", "mapMutations", "mapState"] and
103+
(
104+
this = vuex().getMember(helperName).getACall() and
105+
namespace = ""
106+
or
107+
exists(API::CallNode call |
108+
call = vuex().getMember("createNamespacedHelpers").getACall() and
109+
namespace = call.getParameter(0).getAValueReachingRhs().getStringValue() + "/" and
110+
this = call.getReturn().getMember(helperName).getACall()
111+
)
112+
)
103113
}
104114

105115
/** Gets the name of the `vuex` method being invoked, such as `mapGetters`. */
@@ -109,10 +119,10 @@ module Vuex {
109119
pragma[noinline]
110120
string getPrefix() {
111121
getNumArgument() = 2 and
112-
result = getArgument(0).getStringValue() + "/"
122+
result = namespace + getParameter(0).getAValueReachingRhs().getStringValue() + "/"
113123
or
114124
getNumArgument() = 1 and
115-
result = ""
125+
result = namespace
116126
}
117127

118128
/**

javascript/ql/test/library-tests/frameworks/Vuex/vuex.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Vue from 'vue';
22
import Vuex from 'vuex';
3-
import { mapGetters, mapState, mapMutations, mapActions } from 'vuex';
3+
import { mapGetters, mapState, mapMutations, mapActions, createNamespacedHelpers } from 'vuex';
44

55
Vue.use(Vuex);
66

@@ -18,6 +18,9 @@ const submoduleB = {
1818
}
1919
};
2020

21+
const { mapGetters: mapGettersA } = createNamespacedHelpers('submoduleA');
22+
const { mapGetters: mapGettersB } = createNamespacedHelpers('submoduleB');
23+
2124
const store = new Vuex.Store({
2225
getters: {
2326
getterWithSink: state => { sink(state.tainted); }, // NOT OK
@@ -72,8 +75,10 @@ const Component = new Vue({
7275
derivedUntainted: state => state.untainted,
7376
}),
7477
...mapState(['tainted2']),
75-
...mapGetters('submoduleA', {fooA: 'foo'}),
76-
...mapGetters('submoduleB', {fooB: 'foo'}),
78+
...mapGetters('submoduleA', {fooA1: 'foo'}),
79+
...mapGettersA({fooA2: 'foo'}),
80+
...mapGetters('submoduleB', {fooB1: 'foo'}),
81+
...mapGettersB({fooB2: 'foo'}),
7782
},
7883
methods: {
7984
doCommitsAndActions() {
@@ -95,8 +100,10 @@ const Component = new Vue({
95100
sink(this.untaintedGetter); // OK
96101
sink(this.derivedUntainted); // OK
97102

98-
sink(this.fooA); // NOT OK
99-
sink(this.fooB); // OK
103+
sink(this.fooA1); // NOT OK
104+
sink(this.fooA2); // NOT OK
105+
sink(this.fooB1); // OK
106+
sink(this.fooB2); // OK
100107
},
101108
...mapMutations({ sneakyTaint3: 'setTainted3' }),
102109
...mapActions({ emitTaint4: 'doTaint4' }),

0 commit comments

Comments
 (0)