mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
JS: Add test for flow summaries
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
uniqueToString
|
||||
uniqueEnclosingCallable
|
||||
uniqueDominator
|
||||
localDominator
|
||||
localSuccessor
|
||||
uniqueDefiningScope
|
||||
variableIsCaptured
|
||||
uniqueLocation
|
||||
uniqueCfgNode
|
||||
uniqueWriteTarget
|
||||
uniqueWriteCfgNode
|
||||
uniqueReadVariable
|
||||
closureMustHaveBody
|
||||
closureAliasMustBeInSameScope
|
||||
variableAccessAstNesting
|
||||
uniqueCallableLocation
|
||||
consistencyOverview
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.javascript.dataflow.internal.VariableCapture::VariableCaptureOutput::ConsistencyChecks
|
||||
@@ -0,0 +1,230 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
uniqueNodeToString
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
| file://:0:0:0:0 | (no string representation) | Node should have one toString but has 0. |
|
||||
parameterCallable
|
||||
localFlowIsLocal
|
||||
readStepIsLocal
|
||||
storeStepIsLocal
|
||||
compatibleTypesReflexive
|
||||
unreachableNodeCCtx
|
||||
localCallNodes
|
||||
postIsNotPre
|
||||
postHasUniquePre
|
||||
uniquePostUpdate
|
||||
postIsInSameCallable
|
||||
reverseRead
|
||||
| tst.js:109:11:113:3 | 'arguments' object of anonymous function | Origin of readStep is missing a PostUpdateNode. |
|
||||
| tst.js:267:28:267:31 | map3 | Origin of readStep is missing a PostUpdateNode. |
|
||||
argHasPostUpdate
|
||||
| tst.js:219:18:219:27 | [source()] | ArgumentNode is missing PostUpdateNode. |
|
||||
postWithInFlow
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[1] in Array method with flow into callback | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[1] in Array#filter | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[1] in Array#find / Array#findLast | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[1] in Array#flatMap | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[1] in Array#forEach / Map#forEach / Set#forEach | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[1] in Array#map | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[1] in Array#reduce / Array#reduceRight | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[2] in 'array.prototype.find' / 'array-find' | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[2] in Array.from(arg, callback, [thisArg]) | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[this] in Array#flatMap | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[this] in Array#forEach / Map#forEach / Set#forEach | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[this] in Array#map | PostUpdateNode should not be the target of local flow. |
|
||||
| file://:0:0:0:0 | [summary] to write: Argument[this] in Array#reduce / Array#reduceRight | PostUpdateNode should not be the target of local flow. |
|
||||
| tst.js:97:24:97:74 | new Pro ... rce())) | PostUpdateNode should not be the target of local flow. |
|
||||
| tst.js:100:3:100:53 | new Pro ... rce())) | PostUpdateNode should not be the target of local flow. |
|
||||
| tst.js:101:3:101:53 | new Pro ... rce())) | PostUpdateNode should not be the target of local flow. |
|
||||
| tst.js:102:3:102:52 | new Pro ... rce())) | PostUpdateNode should not be the target of local flow. |
|
||||
| tst.js:103:3:103:52 | new Pro ... rce())) | PostUpdateNode should not be the target of local flow. |
|
||||
| tst.js:250:15:250:23 | new Map() | PostUpdateNode should not be the target of local flow. |
|
||||
| tst.js:258:16:258:24 | new Map() | PostUpdateNode should not be the target of local flow. |
|
||||
| tst.js:264:16:264:24 | new Map() | PostUpdateNode should not be the target of local flow. |
|
||||
viableImplInCallContextTooLarge
|
||||
uniqueParameterNodeAtPosition
|
||||
uniqueParameterNodePosition
|
||||
uniqueContentApprox
|
||||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
| tst.js:30:8:30:37 | flowInt ... urce()) | tst.js:30:8:30:41 | flowInt ... ()).pop (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:30:8:30:37 | flowInt ... urce()) | tst.js:30:8:30:43 | flowInt ... ).pop() | Multiple calls for argument node. |
|
||||
| tst.js:32:39:32:42 | Math | tst.js:32:39:32:49 | Math.random (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:32:39:32:42 | Math | tst.js:32:39:32:51 | Math.random() | Multiple calls for argument node. |
|
||||
| tst.js:54:25:54:31 | Promise | tst.js:54:25:54:39 | Promise.resolve (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:54:25:54:31 | Promise | tst.js:54:25:54:49 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:55:25:55:31 | Promise | tst.js:55:25:55:39 | Promise.resolve (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:55:25:55:31 | Promise | tst.js:55:25:55:47 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:55:25:55:47 | Promise ... "safe") | tst.js:55:25:55:52 | Promise ... ").then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:55:25:55:47 | Promise ... "safe") | tst.js:55:25:55:67 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:56:25:56:31 | Promise | tst.js:56:25:56:39 | Promise.resolve (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:56:25:56:31 | Promise | tst.js:56:25:56:47 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:56:25:56:47 | Promise ... "safe") | tst.js:56:25:56:52 | Promise ... ").then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:56:25:56:47 | Promise ... "safe") | tst.js:56:25:56:65 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:57:25:57:31 | Promise | tst.js:57:25:57:39 | Promise.resolve (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:57:25:57:31 | Promise | tst.js:57:25:57:49 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:57:25:57:49 | Promise ... urce()) | tst.js:57:25:57:54 | Promise ... )).then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:57:25:57:49 | Promise ... urce()) | tst.js:57:25:57:67 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:59:25:59:31 | Promise | tst.js:59:25:59:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:59:25:59:31 | Promise | tst.js:59:25:59:48 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:60:25:60:31 | Promise | tst.js:60:25:60:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:60:25:60:31 | Promise | tst.js:60:25:60:48 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:60:25:60:48 | Promise ... urce()) | tst.js:60:25:60:53 | Promise ... )).then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:60:25:60:48 | Promise ... urce()) | tst.js:60:25:60:74 | Promise ... y => y) | Multiple calls for argument node. |
|
||||
| tst.js:61:25:61:31 | Promise | tst.js:61:25:61:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:61:25:61:31 | Promise | tst.js:61:25:61:48 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:61:25:61:48 | Promise ... urce()) | tst.js:61:25:61:53 | Promise ... )).then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:61:25:61:48 | Promise ... urce()) | tst.js:61:25:61:74 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:62:25:62:31 | Promise | tst.js:62:25:62:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:62:25:62:31 | Promise | tst.js:62:25:62:46 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:62:25:62:46 | Promise ... "safe") | tst.js:62:25:62:51 | Promise ... ").then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:62:25:62:46 | Promise ... "safe") | tst.js:62:25:62:67 | Promise ... y => y) | Multiple calls for argument node. |
|
||||
| tst.js:64:25:64:31 | Promise | tst.js:64:25:64:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:64:25:64:31 | Promise | tst.js:64:25:64:48 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:65:25:65:31 | Promise | tst.js:65:25:65:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:65:25:65:31 | Promise | tst.js:65:25:65:48 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:65:25:65:48 | Promise ... urce()) | tst.js:65:25:65:54 | Promise ... ).catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:65:25:65:48 | Promise ... urce()) | tst.js:65:25:65:66 | Promise ... => err) | Multiple calls for argument node. |
|
||||
| tst.js:66:25:66:31 | Promise | tst.js:66:25:66:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:66:25:66:31 | Promise | tst.js:66:25:66:48 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:66:25:66:48 | Promise ... urce()) | tst.js:66:25:66:54 | Promise ... ).catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:66:25:66:48 | Promise ... urce()) | tst.js:66:25:66:69 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:67:25:67:31 | Promise | tst.js:67:25:67:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:67:25:67:31 | Promise | tst.js:67:25:67:46 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:67:25:67:46 | Promise ... "safe") | tst.js:67:25:67:52 | Promise ... ).catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:67:25:67:46 | Promise ... "safe") | tst.js:67:25:67:64 | Promise ... => err) | Multiple calls for argument node. |
|
||||
| tst.js:69:25:69:31 | Promise | tst.js:69:25:69:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:69:25:69:31 | Promise | tst.js:69:25:69:48 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:69:25:69:48 | Promise ... urce()) | tst.js:69:25:69:53 | Promise ... )).then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:69:25:69:48 | Promise ... urce()) | tst.js:69:25:69:66 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:69:25:69:66 | Promise ... "safe") | tst.js:69:25:69:72 | Promise ... ).catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:69:25:69:66 | Promise ... "safe") | tst.js:69:25:69:84 | Promise ... => err) | Multiple calls for argument node. |
|
||||
| tst.js:71:25:71:31 | Promise | tst.js:71:25:71:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:71:25:71:31 | Promise | tst.js:71:25:71:48 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:71:25:71:48 | Promise ... urce()) | tst.js:71:25:71:56 | Promise ... finally (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:71:25:71:48 | Promise ... urce()) | tst.js:71:25:71:70 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:71:25:71:70 | Promise ... "safe") | tst.js:71:25:71:76 | Promise ... ).catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:71:25:71:70 | Promise ... "safe") | tst.js:71:25:71:88 | Promise ... => err) | Multiple calls for argument node. |
|
||||
| tst.js:72:25:72:31 | Promise | tst.js:72:25:72:39 | Promise.resolve (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:72:25:72:31 | Promise | tst.js:72:25:72:49 | Promise ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:72:25:72:49 | Promise ... urce()) | tst.js:72:25:72:57 | Promise ... finally (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:72:25:72:49 | Promise ... urce()) | tst.js:72:25:72:71 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:72:25:72:71 | Promise ... "safe") | tst.js:72:25:72:76 | Promise ... ").then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:72:25:72:71 | Promise ... "safe") | tst.js:72:25:72:88 | Promise ... => err) | Multiple calls for argument node. |
|
||||
| tst.js:73:25:73:31 | Promise | tst.js:73:25:73:38 | Promise.reject (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:73:25:73:31 | Promise | tst.js:73:25:73:46 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:73:25:73:46 | Promise ... "safe") | tst.js:73:25:73:54 | Promise ... finally (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:73:25:73:46 | Promise ... "safe") | tst.js:73:25:73:80 | Promise ... ce() }) | Multiple calls for argument node. |
|
||||
| tst.js:73:25:73:80 | Promise ... ce() }) | tst.js:73:25:73:86 | Promise ... ).catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:73:25:73:80 | Promise ... ce() }) | tst.js:73:25:73:98 | Promise ... => err) | Multiple calls for argument node. |
|
||||
| tst.js:75:3:75:9 | Promise | tst.js:75:3:75:17 | Promise.resolve (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:75:3:75:9 | Promise | tst.js:75:3:75:25 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:75:3:75:25 | Promise ... "safe") | tst.js:75:3:76:9 | Promise ... .then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:75:3:75:25 | Promise ... "safe") | tst.js:75:3:76:35 | Promise ... e(); }) | Multiple calls for argument node. |
|
||||
| tst.js:75:3:76:35 | Promise ... e(); }) | tst.js:75:3:77:10 | Promise ... .catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:75:3:76:35 | Promise ... e(); }) | tst.js:75:3:79:6 | Promise ... \\n }) | Multiple calls for argument node. |
|
||||
| tst.js:81:3:81:9 | Promise | tst.js:81:3:81:17 | Promise.resolve (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:81:3:81:9 | Promise | tst.js:81:3:81:25 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:81:3:81:25 | Promise ... "safe") | tst.js:81:3:82:9 | Promise ... .then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:81:3:81:25 | Promise ... "safe") | tst.js:81:3:82:35 | Promise ... e(); }) | Multiple calls for argument node. |
|
||||
| tst.js:81:3:82:35 | Promise ... e(); }) | tst.js:81:3:83:9 | Promise ... .then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:81:3:82:35 | Promise ... e(); }) | tst.js:81:3:83:22 | Promise ... "safe") | Multiple calls for argument node. |
|
||||
| tst.js:81:3:83:22 | Promise ... "safe") | tst.js:81:3:84:10 | Promise ... .catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:81:3:83:22 | Promise ... "safe") | tst.js:81:3:86:6 | Promise ... \\n }) | Multiple calls for argument node. |
|
||||
| tst.js:89:3:89:27 | flowInt ... urce()) | tst.js:89:3:89:32 | flowInt ... )).then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:89:3:89:27 | flowInt ... urce()) | tst.js:89:3:89:54 | flowInt ... value)) | Multiple calls for argument node. |
|
||||
| tst.js:100:3:100:53 | new Pro ... rce())) | tst.js:100:3:100:58 | new Pro ... )).then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:100:3:100:53 | new Pro ... rce())) | tst.js:100:3:100:72 | new Pro ... ink(x)) | Multiple calls for argument node. |
|
||||
| tst.js:101:3:101:53 | new Pro ... rce())) | tst.js:101:3:101:59 | new Pro ... ).catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:101:3:101:53 | new Pro ... rce())) | tst.js:101:3:101:77 | new Pro ... k(err)) | Multiple calls for argument node. |
|
||||
| tst.js:102:3:102:52 | new Pro ... rce())) | tst.js:102:3:102:57 | new Pro ... )).then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:102:3:102:52 | new Pro ... rce())) | tst.js:102:3:102:71 | new Pro ... ink(x)) | Multiple calls for argument node. |
|
||||
| tst.js:103:3:103:52 | new Pro ... rce())) | tst.js:103:3:103:58 | new Pro ... ).catch (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:103:3:103:52 | new Pro ... rce())) | tst.js:103:3:103:76 | new Pro ... k(err)) | Multiple calls for argument node. |
|
||||
| tst.js:105:3:105:9 | Promise | tst.js:105:3:105:13 | Promise.all (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:105:3:105:9 | Promise | tst.js:105:3:109:4 | Promise ... e"\\n ]) | Multiple calls for argument node. |
|
||||
| tst.js:105:3:109:4 | Promise ... e"\\n ]) | tst.js:105:3:109:9 | Promise ... ]).then (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:105:3:109:4 | Promise ... e"\\n ]) | tst.js:105:3:113:4 | Promise ... OK\\n }) | Multiple calls for argument node. |
|
||||
| tst.js:170:19:170:25 | Promise | tst.js:170:19:170:33 | Promise.resolve (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:170:19:170:25 | Promise | tst.js:170:19:170:38 | Promise.resolve(obj) | Multiple calls for argument node. |
|
||||
| tst.js:209:3:209:7 | array | tst.js:209:3:209:12 | array.push (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:209:3:209:7 | array | tst.js:209:3:209:38 | array.p ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:210:8:210:12 | array | tst.js:210:8:210:16 | array.pop (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:210:8:210:12 | array | tst.js:210:8:210:18 | array.pop() | Multiple calls for argument node. |
|
||||
| tst.js:213:3:213:8 | array2 | tst.js:213:3:213:13 | array2.push (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:213:3:213:8 | array2 | tst.js:213:3:213:23 | array2. ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:214:3:214:8 | array2 | tst.js:214:3:214:13 | array2.push (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:214:3:214:8 | array2 | tst.js:214:3:214:21 | array2.push("safe") | Multiple calls for argument node. |
|
||||
| tst.js:215:3:215:8 | array2 | tst.js:215:3:215:13 | array2.push (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:215:3:215:8 | array2 | tst.js:215:3:215:21 | array2.push("safe") | Multiple calls for argument node. |
|
||||
| tst.js:216:3:216:8 | array2 | tst.js:216:3:216:16 | array2.forEach (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:216:3:216:8 | array2 | tst.js:216:3:216:30 | array2. ... ink(x)) | Multiple calls for argument node. |
|
||||
| tst.js:219:3:219:8 | array3 | tst.js:219:3:219:13 | array3.push (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:219:3:219:8 | array3 | tst.js:219:3:219:28 | array3. ... rce()]) | Multiple calls for argument node. |
|
||||
| tst.js:220:3:220:8 | array3 | tst.js:220:3:220:16 | array3.forEach (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:220:3:220:8 | array3 | tst.js:220:3:220:30 | array3. ... ink(x)) | Multiple calls for argument node. |
|
||||
| tst.js:223:12:223:32 | Array.p ... e.slice | tst.js:223:12:223:37 | Array.p ... ce.call (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:223:12:223:32 | Array.p ... e.slice | tst.js:223:12:223:45 | Array.p ... array4) | Multiple calls for argument node. |
|
||||
| tst.js:223:12:223:32 | Array.p ... e.slice | tst.js:223:12:223:45 | reflective call | Multiple calls for argument node. |
|
||||
| tst.js:223:39:223:44 | array4 | tst.js:223:12:223:45 | Array.p ... array4) | Multiple calls for argument node. |
|
||||
| tst.js:223:39:223:44 | array4 | tst.js:223:12:223:45 | reflective call | Multiple calls for argument node. |
|
||||
| tst.js:224:8:224:13 | array4 | tst.js:224:8:224:17 | array4.pop (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:224:8:224:13 | array4 | tst.js:224:8:224:19 | array4.pop() | Multiple calls for argument node. |
|
||||
| tst.js:226:3:226:12 | [source()] | tst.js:226:3:226:20 | [source()].forEach (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:226:3:226:12 | [source()] | tst.js:226:3:226:68 | [source ... p()) }) | Multiple calls for argument node. |
|
||||
| tst.js:226:54:226:58 | array | tst.js:226:54:226:62 | array.pop (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:226:54:226:58 | array | tst.js:226:54:226:64 | array.pop() | Multiple calls for argument node. |
|
||||
| tst.js:228:3:228:8 | array5 | tst.js:228:3:228:16 | array5.forEach (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:228:3:228:8 | array5 | tst.js:228:3:228:64 | array5. ... p()) }) | Multiple calls for argument node. |
|
||||
| tst.js:228:50:228:54 | array | tst.js:228:50:228:58 | array.pop (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:228:50:228:54 | array | tst.js:228:50:228:60 | array.pop() | Multiple calls for argument node. |
|
||||
| tst.js:229:3:229:10 | ["safe"] | tst.js:229:3:229:18 | ["safe"].forEach (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:229:3:229:10 | ["safe"] | tst.js:229:3:229:66 | ["safe" ... p()) }) | Multiple calls for argument node. |
|
||||
| tst.js:229:52:229:56 | array | tst.js:229:52:229:60 | array.pop (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:229:52:229:56 | array | tst.js:229:52:229:62 | array.pop() | Multiple calls for argument node. |
|
||||
| tst.js:251:3:251:5 | map | tst.js:251:3:251:9 | map.set (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:251:3:251:5 | map | tst.js:251:3:251:26 | map.set ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:252:3:252:5 | map | tst.js:252:3:252:9 | map.set (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:252:3:252:5 | map | tst.js:252:3:252:24 | map.set ... 'safe') | Multiple calls for argument node. |
|
||||
| tst.js:254:8:254:10 | map | tst.js:254:8:254:14 | map.get (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:254:8:254:10 | map | tst.js:254:8:254:21 | map.get('foo') | Multiple calls for argument node. |
|
||||
| tst.js:255:8:255:10 | map | tst.js:255:8:255:14 | map.get (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:255:8:255:10 | map | tst.js:255:8:255:21 | map.get('bar') | Multiple calls for argument node. |
|
||||
| tst.js:256:8:256:10 | map | tst.js:256:8:256:14 | map.get (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:256:8:256:10 | map | tst.js:256:8:256:27 | map.get(getUnkown()) | Multiple calls for argument node. |
|
||||
| tst.js:259:3:259:6 | map2 | tst.js:259:3:259:10 | map2.set (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:259:3:259:6 | map2 | tst.js:259:3:259:33 | map2.se ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:260:8:260:11 | map2 | tst.js:260:8:260:15 | map2.get (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:260:8:260:11 | map2 | tst.js:260:8:260:22 | map2.get('foo') | Multiple calls for argument node. |
|
||||
| tst.js:261:8:261:11 | map2 | tst.js:261:8:261:15 | map2.get (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:261:8:261:11 | map2 | tst.js:261:8:261:22 | map2.get('bar') | Multiple calls for argument node. |
|
||||
| tst.js:262:8:262:11 | map2 | tst.js:262:8:262:15 | map2.get (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:262:8:262:11 | map2 | tst.js:262:8:262:28 | map2.ge ... kown()) | Multiple calls for argument node. |
|
||||
| tst.js:265:3:265:6 | map3 | tst.js:265:3:265:10 | map3.set (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:265:3:265:6 | map3 | tst.js:265:3:265:27 | map3.se ... urce()) | Multiple calls for argument node. |
|
||||
| tst.js:266:3:266:6 | map3 | tst.js:266:3:266:14 | map3.forEach (as accessor call) | Multiple calls for argument node. |
|
||||
| tst.js:266:3:266:6 | map3 | tst.js:266:3:266:36 | map3.fo ... value)) | Multiple calls for argument node. |
|
||||
@@ -0,0 +1,2 @@
|
||||
import javascript
|
||||
import semmle.javascript.dataflow.internal.DataFlowImplConsistency::Consistency
|
||||
37
javascript/ql/test/library-tests/FlowSummary/Summaries.qll
Normal file
37
javascript/ql/test/library-tests/FlowSummary/Summaries.qll
Normal file
@@ -0,0 +1,37 @@
|
||||
import javascript
|
||||
import semmle.javascript.dataflow.FlowSummary
|
||||
|
||||
class MkSummary extends SummarizedCallable {
|
||||
private CallExpr mkSummary;
|
||||
|
||||
MkSummary() {
|
||||
mkSummary.getCalleeName() = "mkSummary" and
|
||||
this =
|
||||
"mkSummary at " + mkSummary.getFile().getRelativePath() + ":" +
|
||||
mkSummary.getLocation().getStartLine()
|
||||
}
|
||||
|
||||
override DataFlow::InvokeNode getACall() {
|
||||
result = mkSummary.flow().(DataFlow::CallNode).getAnInvocation()
|
||||
}
|
||||
|
||||
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
|
||||
preservesValue = true and
|
||||
(
|
||||
// mkSummary(input, output)
|
||||
input = mkSummary.getArgument(0).getStringValue() and
|
||||
output = mkSummary.getArgument(1).getStringValue()
|
||||
or
|
||||
// mkSummary([
|
||||
// [input1, output1],
|
||||
// [input2, output2],
|
||||
// ...
|
||||
// ])
|
||||
exists(ArrayExpr pair |
|
||||
pair = mkSummary.getArgument(0).(ArrayExpr).getAnElement() and
|
||||
input = pair.getElement(0).getStringValue() and
|
||||
output = pair.getElement(1).getStringValue()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
36
javascript/ql/test/library-tests/FlowSummary/test.ql
Normal file
36
javascript/ql/test/library-tests/FlowSummary/test.ql
Normal file
@@ -0,0 +1,36 @@
|
||||
import javascript
|
||||
import testUtilities.ConsistencyChecking
|
||||
import Summaries
|
||||
|
||||
DataFlow::CallNode getACall(string name) {
|
||||
result.getCalleeName() = name
|
||||
or
|
||||
result.getCalleeNode().getALocalSource() = DataFlow::globalVarRef(name)
|
||||
}
|
||||
|
||||
module ConfigArg implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node = getACall("source") }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node = getACall("sink").getAnArgument() }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node.(DataFlow::InvokeNode).getCalleeName().matches("sanitizer_%") or
|
||||
node = DataFlow::MakeBarrierGuard<BasicBarrierGuard>::getABarrierNode()
|
||||
}
|
||||
}
|
||||
|
||||
module Configuration = DataFlow::Global<ConfigArg>;
|
||||
|
||||
class BasicBarrierGuard extends DataFlow::CallNode {
|
||||
BasicBarrierGuard() { this = getACall("isSafe") }
|
||||
|
||||
predicate blocksExpr(boolean outcome, Expr e) {
|
||||
outcome = true and e = this.getArgument(0).asExpr()
|
||||
}
|
||||
}
|
||||
|
||||
class ConsistencyConfig extends ConsistencyConfiguration {
|
||||
ConsistencyConfig() { this = "ConsistencyConfig" }
|
||||
|
||||
override DataFlow::Node getAnAlert() { Configuration::flow(_, result) }
|
||||
}
|
||||
270
javascript/ql/test/library-tests/FlowSummary/tst.js
Normal file
270
javascript/ql/test/library-tests/FlowSummary/tst.js
Normal file
@@ -0,0 +1,270 @@
|
||||
function m1() {
|
||||
const flowThrough = mkSummary("Argument[0]", "ReturnValue");
|
||||
sink(flowThrough(source())); // NOT OK
|
||||
sink(flowThrough(source() + "x")); // OK - we are not tracking taint in this test
|
||||
sink(flowThrough("x")); // OK
|
||||
}
|
||||
|
||||
function m2() {
|
||||
const flowIntoProp = mkSummary("Argument[0]", "ReturnValue.Member[prop]");
|
||||
sink(flowIntoProp(source()).prop); // NOT OK
|
||||
sink(flowIntoProp(source()).prop2); // OK
|
||||
sink(flowIntoProp(source())); // OK
|
||||
}
|
||||
|
||||
function m3() {
|
||||
const flowOutOfProp = mkSummary("Argument[0].Member[prop]", "ReturnValue");
|
||||
sink(flowOutOfProp({ prop: source() })); // NOT OK
|
||||
sink(flowOutOfProp({ prop2: source() })); // OK
|
||||
sink(flowOutOfProp(source())); // OK
|
||||
|
||||
const obj = {};
|
||||
obj.prop = source();
|
||||
sink(flowOutOfProp(obj)); // NOT OK
|
||||
sink(obj); // OK
|
||||
sink(obj.prop); // NOT OK
|
||||
}
|
||||
|
||||
function m4() {
|
||||
const flowIntoArrayElement = mkSummary("Argument[0]", "ReturnValue.ArrayElement");
|
||||
sink(flowIntoArrayElement(source()).pop()); // NOT OK
|
||||
sink(flowIntoArrayElement(source())[0]); // NOT OK [INCONSISTENCY]
|
||||
sink(flowIntoArrayElement(source())[Math.random()]); // NOT OK
|
||||
sink(flowIntoArrayElement(source()).prop); // OK
|
||||
}
|
||||
|
||||
function m5() {
|
||||
const flowOutOfInnerCallback = mkSummary("Argument[0].Parameter[0].Argument[0]", "ReturnValue");
|
||||
sink(flowOutOfInnerCallback(cb => { cb(source()); })); // NOT OK [INCONSISTENCY]
|
||||
}
|
||||
|
||||
async function m6() {
|
||||
const flowOutOfPromise = mkSummary("Argument[0].Awaited", "ReturnValue");
|
||||
const flowIntoPromise = mkSummary("Argument[0]", "ReturnValue.Awaited");
|
||||
|
||||
sink(flowOutOfPromise(flowIntoPromise(source()))); // NOT OK (although the synchronous flow is technically not possible)
|
||||
|
||||
let data = { prop: source() };
|
||||
sink(flowOutOfPromise(flowIntoPromise(data)).prop); // NOT OK
|
||||
sink(flowOutOfPromise(flowIntoPromise(flowIntoPromise(data))).prop); // NOT OK
|
||||
sink(flowOutOfPromise(flowOutOfPromise(flowIntoPromise(data))).prop); // NOT OK
|
||||
sink(flowOutOfPromise(data).prop); // NOT OK - because Awaited allows pass-through of a non-promise value
|
||||
sink(flowIntoPromise(data).prop); // OK - promise object does not have the 'prop' property
|
||||
|
||||
sink(flowOutOfPromise(Promise.resolve(source()))); // NOT OK
|
||||
sink(flowOutOfPromise(Promise.resolve("safe").then(x => source()))); // NOT OK
|
||||
sink(flowOutOfPromise(Promise.resolve("safe").then(x => "safe"))); // OK
|
||||
sink(flowOutOfPromise(Promise.resolve(source()).then(x => "safe"))); // OK
|
||||
|
||||
sink(flowOutOfPromise(Promise.reject(source()))); // OK
|
||||
sink(flowOutOfPromise(Promise.reject(source()).then(x => "safe", y => y))); // NOT OK
|
||||
sink(flowOutOfPromise(Promise.reject(source()).then(x => x, y => "safe"))); // OK
|
||||
sink(flowOutOfPromise(Promise.reject("safe").then(x => x, y => y))); // OK
|
||||
|
||||
sink(flowOutOfPromise(Promise.reject(source()))); // OK
|
||||
sink(flowOutOfPromise(Promise.reject(source()).catch(err => err))); // NOT OK
|
||||
sink(flowOutOfPromise(Promise.reject(source()).catch(err => "safe"))); // OK
|
||||
sink(flowOutOfPromise(Promise.reject("safe").catch(err => err))); // OK
|
||||
|
||||
sink(flowOutOfPromise(Promise.reject(source()).then(x => "safe").catch(err => err))); // NOT OK
|
||||
|
||||
sink(flowOutOfPromise(Promise.reject(source()).finally(() => "safe").catch(err => err))); // NOT OK
|
||||
sink(flowOutOfPromise(Promise.resolve(source()).finally(() => "safe").then(err => err))); // NOT OK
|
||||
sink(flowOutOfPromise(Promise.reject("safe").finally(() => { throw source() }).catch(err => err))); // NOT OK
|
||||
|
||||
Promise.resolve("safe")
|
||||
.then(x => { throw source(); })
|
||||
.catch(err => {
|
||||
sink(err); // NOT OK
|
||||
});
|
||||
|
||||
Promise.resolve("safe")
|
||||
.then(x => { throw source(); })
|
||||
.then(x => "safe")
|
||||
.catch(err => {
|
||||
sink(err); // NOT OK
|
||||
});
|
||||
|
||||
sink(await flowIntoPromise(source())); // NOT OK
|
||||
flowIntoPromise(source()).then(value => sink(value)); // NOT OK
|
||||
sink(await flowIntoPromise(flowIntoPromise(source()))); // NOT OK
|
||||
|
||||
async function makePromise() {
|
||||
return source();
|
||||
}
|
||||
sink(flowOutOfPromise(makePromise())); // NOT OK
|
||||
|
||||
let taintedPromise = new Promise((resolve, reject) => resolve(source()));
|
||||
sink(flowOutOfPromise(taintedPromise)); // NOT OK
|
||||
|
||||
new Promise((resolve, reject) => resolve(source())).then(x => sink(x)); // NOT OK
|
||||
new Promise((resolve, reject) => resolve(source())).catch(err => sink(err)); // OK
|
||||
new Promise((resolve, reject) => reject(source())).then(x => sink(x)); // OK
|
||||
new Promise((resolve, reject) => reject(source())).catch(err => sink(err)); // NOT OK
|
||||
|
||||
Promise.all([
|
||||
flowIntoPromise(source()),
|
||||
source(),
|
||||
"safe"
|
||||
]).then(([x1, x2, x3]) => {
|
||||
sink(x1); // NOT OK
|
||||
sink(x2); // NOT OK
|
||||
sink(x3); // OK
|
||||
});
|
||||
}
|
||||
|
||||
function m8() {
|
||||
const flowOutOfCallback = mkSummary("Argument[0].ReturnValue", "ReturnValue");
|
||||
|
||||
sink(flowOutOfCallback(() => source())); // NOT OK
|
||||
sink(flowOutOfCallback((source))); // OK
|
||||
|
||||
function sourceCallback() {
|
||||
return source();
|
||||
}
|
||||
sink(flowOutOfCallback(sourceCallback)); // NOT OK
|
||||
}
|
||||
|
||||
function m9() {
|
||||
const flowIntoCallback = mkSummary("Argument[0]", "Argument[1].Parameter[0]");
|
||||
|
||||
sink(flowIntoCallback(source(), x => sink(x))); // NOT OK
|
||||
sink(flowIntoCallback("safe", x => sink(x))); // OK
|
||||
sink(flowIntoCallback(source(), x => ignore(x))); // OK
|
||||
sink(flowIntoCallback("safe", x => ignore(x))); // OK
|
||||
}
|
||||
|
||||
function m10() {
|
||||
const flowThroughCallback = mkSummary([
|
||||
["Argument[0]", "Argument[1].Parameter[0]"],
|
||||
["Argument[1].ReturnValue", "ReturnValue"]
|
||||
]);
|
||||
|
||||
sink(flowThroughCallback(source(), x => x)); // NOT OK
|
||||
sink(flowThroughCallback(source(), x => "safe")); // OK
|
||||
sink(flowThroughCallback("safe", x => x)); // OK
|
||||
sink(flowThroughCallback("safe", x => "safe")); // OK
|
||||
}
|
||||
|
||||
function m11() {
|
||||
const flowFromSideEffectOnParameter = mkSummary("Argument[0].Parameter[0].Member[prop]", "ReturnValue");
|
||||
|
||||
let data = flowFromSideEffectOnParameter(param => {
|
||||
param.prop = source();
|
||||
});
|
||||
sink(data); // NOT OK
|
||||
|
||||
function manullyWritten(param) {
|
||||
param.prop = source();
|
||||
}
|
||||
let obj = {};
|
||||
manullyWritten(obj);
|
||||
sink(obj.prop); // NOT OK
|
||||
}
|
||||
|
||||
async function m13() {
|
||||
async function testStoreBack(x) {
|
||||
(await x).prop = source();
|
||||
}
|
||||
const obj = {};
|
||||
const promise = Promise.resolve(obj);
|
||||
testStoreBack(promise);
|
||||
sink(obj.prop); // NOT OK [INCONSISTENCY]
|
||||
sink(promise.prop); // OK [INCONSISTENCY]
|
||||
sink((await promise).prop); // NOT OK
|
||||
|
||||
const obj2 = {};
|
||||
testStoreBack(obj2);
|
||||
sink(obj2.prop);; // NOT OK
|
||||
}
|
||||
|
||||
function m14() {
|
||||
const flowOutOfAnyArgument = mkSummary("Argument[0..]", "ReturnValue");
|
||||
sink(flowOutOfAnyArgument(source())); // NOT OK
|
||||
sink(flowOutOfAnyArgument(source(), "safe", "safe")); // NOT OK
|
||||
sink(flowOutOfAnyArgument("safe", source(), "safe")); // NOT OK
|
||||
sink(flowOutOfAnyArgument("safe", "safe", source())); // NOT OK
|
||||
sink(flowOutOfAnyArgument("safe", "safe", "safe")); // OK
|
||||
|
||||
const flowOutOfAnyArgumentExceptFirst = mkSummary("Argument[1..]", "ReturnValue");
|
||||
sink(flowOutOfAnyArgumentExceptFirst(source())); // OK
|
||||
sink(flowOutOfAnyArgumentExceptFirst(source(), "safe", "safe")); // OK
|
||||
sink(flowOutOfAnyArgumentExceptFirst("safe", source(), "safe")); // NOT OK
|
||||
sink(flowOutOfAnyArgumentExceptFirst("safe", "safe", source())); // NOT OK
|
||||
sink(flowOutOfAnyArgumentExceptFirst("safe", "safe", "safe")); // OK
|
||||
|
||||
const flowIntoAnyParameter = mkSummary("Argument[0]", "Argument[1].Parameter[0..]");
|
||||
flowIntoAnyParameter(source(), (x1, x2, x3) => sink(x1)); // NOT OK
|
||||
flowIntoAnyParameter(source(), (x1, x2, x3) => sink(x2)); // NOT OK
|
||||
flowIntoAnyParameter(source(), (x1, x2, x3) => sink(x3)); // NOT OK
|
||||
|
||||
const flowIntoAnyParameterExceptFirst = mkSummary("Argument[0]", "Argument[1].Parameter[1..]");
|
||||
flowIntoAnyParameterExceptFirst(source(), (x1, x2, x3) => sink(x1)); // OK
|
||||
flowIntoAnyParameterExceptFirst(source(), (x1, x2, x3) => sink(x2)); // NOT OK
|
||||
flowIntoAnyParameterExceptFirst(source(), (x1, x2, x3) => sink(x3)); // NOT OK
|
||||
}
|
||||
|
||||
function m15() {
|
||||
const array = [];
|
||||
array.push("safe", "safe", source());
|
||||
sink(array.pop()); // NOT OK
|
||||
|
||||
const array2 = [];
|
||||
array2.push(source());
|
||||
array2.push("safe");
|
||||
array2.push("safe");
|
||||
array2.forEach(x => sink(x)); // NOT OK
|
||||
|
||||
const array3 = [];
|
||||
array3.push(...[source()]);
|
||||
array3.forEach(x => sink(x)); // NOT OK
|
||||
|
||||
const array4 = [source()];
|
||||
array4 = Array.prototype.slice.call(array4);
|
||||
sink(array4.pop()); // NOT OK
|
||||
|
||||
[source()].forEach((value, index, array) => { sink(array.pop()) }); // NOT OK
|
||||
const array5 = [source()];
|
||||
array5.forEach((value, index, array) => { sink(array.pop()) }); // NOT OK
|
||||
["safe"].forEach((value, index, array) => { sink(array.pop()) }); // OK
|
||||
}
|
||||
|
||||
function m16() {
|
||||
const array0 = [source(), 'safe', 'safe'];
|
||||
sink(array0[0]); // NOT OK
|
||||
sink(array0[1]); // OK
|
||||
sink(array0[2]); // OK
|
||||
|
||||
const array1 = ['safe', source(), 'safe'];
|
||||
sink(array1[0]); // OK
|
||||
sink(array1[1]); // NOT OK
|
||||
sink(array1[2]); // OK
|
||||
|
||||
const array2 = ['safe', 'safe', source()];
|
||||
sink(array2[0]); // OK
|
||||
sink(array2[1]); // OK
|
||||
sink(array2[2]); // NOT OK
|
||||
}
|
||||
|
||||
function m17() {
|
||||
const map = new Map();
|
||||
map.set('foo', source());
|
||||
map.set('bar', 'safe');
|
||||
|
||||
sink(map.get('foo')); // NOT OK
|
||||
sink(map.get('bar')); // OK
|
||||
sink(map.get(getUnkown())); // NOT OK
|
||||
|
||||
const map2 = new Map();
|
||||
map2.set(getUnkown(), source());
|
||||
sink(map2.get('foo')); // NOT OK
|
||||
sink(map2.get('bar')); // NOT OK
|
||||
sink(map2.get(getUnkown())); // NOT OK
|
||||
|
||||
const map3 = new Map();
|
||||
map3.set('foo', source());
|
||||
map3.forEach(value => sink(value)); // NOT OK
|
||||
for (let [key, value] of map3) {
|
||||
sink(value); // NOT OK
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user