From f2ca2134d167cbefc0edeb331e5c43cabec0620f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 20 Jun 2021 22:12:18 +0200 Subject: [PATCH] refactor `promisify` models into a module --- .../ql/src/semmle/javascript/ApiGraphs.qll | 4 +-- .../ql/src/semmle/javascript/Promises.qll | 30 +++++++++++++++++++ .../javascript/frameworks/NodeJSLib.qll | 13 ++------ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 590142590a4..bf8ff610dc7 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -686,9 +686,7 @@ module API { promisified = false and boundArgs = 0 or - exists(DataFlow::CallNode promisify | - promisify = DataFlow::moduleImport(["util", "bluebird"]).getAMemberCall("promisify") - | + exists(Promisify::PromisifyCall promisify | trackUseNode(nd, false, boundArgs, t.continue()).flowsTo(promisify.getArgument(0)) and promisified = true and result = promisify diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 9190473201e..8139f10e0f4 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -659,3 +659,33 @@ private module DynamicImportSteps { } } } + +/** + * Provides classes modeling libraries implementing `promisify` functions. + * That is, functions that convert callback style functions to functions that return a promise. + */ +module Promisify { + /** + * Gets a call to a `promisifyAll` function. + * E.g. `require("bluebird").promisifyAll(...)`. + */ + class PromisifyAllCall extends DataFlow::CallNode { + PromisifyAllCall() { + this = + [ + DataFlow::moduleMember("bluebird", "promisifyAll"), + DataFlow::moduleImport("util-promisifyall") + ].getACall() + } + } + + /** + * Gets a call to a `promisify` function. + * E.g. `require("util").promisify(...)`. + */ + class PromisifyCall extends DataFlow::CallNode { + PromisifyCall() { + this = DataFlow::moduleImport(["util", "bluebird"]).getAMemberCall("promisify") + } + } +} diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index 840e9ea9b78..a7ceb09a546 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -472,14 +472,9 @@ module NodeJSLib { result = pred.track(t2, t) or t.continue() = t2 and - exists(DataFlow::CallNode promisifyAllCall | + exists(Promisify::PromisifyAllCall promisifyAllCall | result = promisifyAllCall and - pred.flowsTo(promisifyAllCall.getArgument(0)) and - promisifyAllCall = - [ - DataFlow::moduleMember("bluebird", "promisifyAll"), - DataFlow::moduleImport("util-promisifyall") - ].getACall() + pred.flowsTo(promisifyAllCall.getArgument(0)) ) or // const fs = require('fs'); @@ -648,9 +643,7 @@ module NodeJSLib { private DataFlow::SourceNode maybePromisified(DataFlow::SourceNode callback) { result = callback or - exists(DataFlow::CallNode promisify | - promisify = DataFlow::moduleMember(["util", "bluebird"], "promisify").getACall() - | + exists(Promisify::PromisifyCall promisify | result = promisify and promisify.getArgument(0).getALocalSource() = callback ) }