diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll index 877b47651ef..b75b388724a 100644 --- a/javascript/ql/src/javascript.qll +++ b/javascript/ql/src/javascript.qll @@ -27,6 +27,7 @@ import semmle.javascript.Extend import semmle.javascript.Externs import semmle.javascript.Files import semmle.javascript.Functions +import semmle.javascript.Generators import semmle.javascript.GlobalAccessPaths import semmle.javascript.HTML import semmle.javascript.HtmlSanitizers diff --git a/javascript/ql/src/semmle/javascript/Generators.qll b/javascript/ql/src/semmle/javascript/Generators.qll new file mode 100644 index 00000000000..eb402add1be --- /dev/null +++ b/javascript/ql/src/semmle/javascript/Generators.qll @@ -0,0 +1,21 @@ +import javascript +private import semmle.javascript.dataflow.internal.PreCallGraphStep + +/** + * Classes and predicates for modelling data-flow for generator functions. + */ +private module GeneratorDataFlow { + private import DataFlow::PseudoProperties + + private class ArrayIteration extends PreCallGraphStep { + override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { + exists(DataFlow::FunctionNode f | f.getFunction().isGenerator() | + prop = iteratorElement() and + exists(YieldExpr yield | yield.getContainer() = f.getFunction() | + pred.asExpr() = yield.getOperand() + ) and + succ = f.getReturnNode() + ) + } + } +} diff --git a/javascript/ql/test/library-tests/Generators/generators.js b/javascript/ql/test/library-tests/Generators/generators.js index a943e336a6d..c0ce436e190 100644 --- a/javascript/ql/test/library-tests/Generators/generators.js +++ b/javascript/ql/test/library-tests/Generators/generators.js @@ -6,7 +6,7 @@ yield source; } for (const x of gen1()) { - sink(x); // NOT OK - but not found yet [INCONSISTENCY] + sink(x); // NOT OK } function *gen2() {