diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll index 047492790602..3d12f6a4a903 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll @@ -1175,6 +1175,7 @@ private predicate parameterPropReadStep( invk = getAwaitOperand(succ) ) and callInputStep(f, invk, arg, parm, cfg) and + prop = pragma[only_bind_into](getARelevantProp(cfg)) and ( read = parm.getAPropertyRead(prop) or @@ -1192,7 +1193,7 @@ private predicate reachesReturn( isRelevant(read, cfg) and returnExpr(f, read, _) and summary = PathSummary::level() and - callInputStep(f, _, _, _, _) // check that a relevant result can exist. + parameterPropReadStep(_, _, _, cfg, _, _, f, _) // check that a relevant result can exist. or exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary | flowStep(read, cfg, mid, oldSummary) and @@ -1202,6 +1203,33 @@ private predicate reachesReturn( ) } +// used in `getARelevantProp`, outlined for performance +pragma[noinline] +private string getARelevantStoreProp(DataFlow::Configuration cfg) { + exists(DataFlow::Node previous | isRelevant(previous, cfg) | + basicStoreStep(previous, _, result) or + isAdditionalStoreStep(previous, _, result, cfg) + ) +} + +// used in `getARelevantProp`, outlined for performance +pragma[noinline] +private string getARelevantLoadProp(DataFlow::Configuration cfg) { + exists(DataFlow::Node previous | isRelevant(previous, cfg) | + basicLoadStep(previous, _, result) or + isAdditionalLoadStep(previous, _, result, cfg) + ) +} + +/** Gets the name of a property that is both loaded and stored according to the exploratory analysis. */ +pragma[noinline] +private string getARelevantProp(DataFlow::Configuration cfg) { + result = getARelevantStoreProp(cfg) and + result = getARelevantLoadProp(cfg) + or + result = getAPropertyUsedInLoadStore(cfg) +} + /** * Holds if the property `prop` of the object `pred` should be loaded into `succ`. */ @@ -1275,6 +1303,7 @@ private predicate reachableFromStoreBase( ) { exists(TPathSummary s1, TPathSummary s2, DataFlow::Node rhs | storeStep(rhs, nd, startProp, cfg, s2) and + startProp = getARelevantProp(cfg) and endProp = startProp and base = nd and exists(boolean hasCall, DataFlow::FlowLabel data | @@ -1300,6 +1329,7 @@ private predicate reachableFromStoreBase( exists(string midProp | reachableFromStoreBase(startProp, midProp, base, mid, cfg, oldSummary, onlyRelevantInCall) and isAdditionalLoadStoreStep(mid, nd, midProp, endProp, cfg) and + endProp = getARelevantProp(cfg) and newSummary = PathSummary::level() ) |