调用非函数¶
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
尝试调用非函数(即基本值或对象)将在运行时导致异常。这适用于使用`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);
}
}