CodeQL 文档

调用非函数

ID: js/call-to-non-callable
Kind: problem
Security severity: 
Severity: error
Precision: high
Tags:
   - correctness
   - external/cwe/cwe-476
Query suites:
   - javascript-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

尝试调用非函数(即基本值或对象)将在运行时导致异常。这适用于使用`new` 的调用和普通调用。

建议

仔细检查所讨论的调用。如果问题在测试期间未被检测到,这可能是因为调用在死代码中,或者没有被测试覆盖。在前一种情况下,删除相关死代码。在后一种情况下,考虑添加一个新的测试。

示例

在以下示例中,函数`processResponse` 接受一个参数`response`,并根据属性`response.status` 的值执行以下两件事之一:如果`response.status` 为 200,则调用函数`processResponseText`(未显示),如果该函数返回`error` 值,则将其作为异常抛出;否则,调用`error` 记录`response.status` 的值。

function error(msg) {
  console.log(msg);
}

function processResponse(response) {
  if (response.status === 200) {
    var error = processResponseText(response.responseText);
    if (error)
       throw error;
  } else {
    error("Unexpected response status " + response.status);
  }
}

请注意,由于 JavaScript 的作用域规则,“else”分支中的`error` 实际上是指在“then”分支中声明的`error` 变量(而不是同名全局函数)。由于该变量在“else”分支中始终为`undefined`,因此尝试调用它将在运行时导致异常。

要解决此问题,可以将`error` 转换为`let` 绑定变量,以避免意外名称捕获

function error(msg) {
  console.log(msg);
}

function processResponse(response) {
  if (response.status === 200) {
    let error = processResponseText(response.responseText);
    if (error)
       throw error;
  } else {
    error("Unexpected response status " + response.status);
  }
}

或者,如果需要 ECMAScript 5 兼容性,可以改名`error` 变量,如本例所示

function error(msg) {
  console.log(msg);
}

function processResponse(response) {
  if (response.status === 200) {
    var err = processResponseText(response.responseText);
    if (err)
       throw err;
  } else {
    error("Unexpected response status " + response.status);
  }
}

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私