mirror of
https://github.com/github/codeql.git
synced 2026-04-21 15:05:56 +02:00
JavaScript: Remove deprecated queries.
These queries have all been deprecated since 1.17 (released in July 2018). I think it's time to say goodbye.
This commit is contained in:
@@ -1,45 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Avoid using <code>x % 2 === 1</code> or <code>x % 2 > 0</code> to check whether a number
|
||||
<code>x</code> is odd, or <code>x % 2 !== 1</code> to check whether it is even.
|
||||
Such code does not work for negative numbers: for example, <code>-5 % 2</code> equals
|
||||
<code>-1</code>, not <code>1</code>.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
Consider using <code>x % 2 !== 0</code> to check for odd parity and <code>x % 2 === 0</code>
|
||||
to check for even parity.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>
|
||||
The following code snippet does not detect -9 as an odd number because <code>-9 % 2</code>
|
||||
is <code>-1</code>, not <code>1</code>.</p>
|
||||
|
||||
<sample src="examples/BadParityCheck.js" />
|
||||
|
||||
<p>
|
||||
The check should be rewritten as follows:
|
||||
</p>
|
||||
|
||||
<sample src="examples/BadParityCheckGood.js" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
|
||||
<li>J. Bloch and N. Gafter, <em>Java Puzzlers: Traps, Pitfalls, and Corner Cases</em>, Puzzle 1. Addison-Wesley, 2005.</li>
|
||||
<li>Ecma International, <i>ECMAScript Language Definition</i>, 5.1 Edition, Section 11.5.3. ECMA, 2011.</li>
|
||||
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,105 +0,0 @@
|
||||
/**
|
||||
* @name Bad parity check
|
||||
* @description Ensure that parity checks take negative numbers into account.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @id js/incomplete-parity-check
|
||||
* @tags reliability
|
||||
* correctness
|
||||
* external/cwe/cwe-480
|
||||
* @precision low
|
||||
* @deprecated This query is prone to false positives. Deprecated since 1.17.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/*
|
||||
* The following predicates implement a simple analysis for identifying
|
||||
* expressions that are guaranteed to only evaluate to non-negative numbers:
|
||||
*
|
||||
* - non-negative number literals
|
||||
* - applications of (), ++, + to expressions known to be non-negative
|
||||
* - references to local variables that are only assigned non-negative values,
|
||||
* never decremented, and never subjected to any compound assignments except
|
||||
* += where the rhs is known to be non-negative
|
||||
*
|
||||
* This is a greatest-fixpoint problem: if we have `x = 0`, `y = x`, `x = y`,
|
||||
* we want to conclude that both `x` and `y` are non-negative. Hence we have
|
||||
* to implement the analysis the other way around, as a conservative check
|
||||
* for negativity.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds if `e` is an expression that is relevant for the maybe-negative analysis.
|
||||
*/
|
||||
predicate relevant(Expr e) {
|
||||
// base case: left operands of `%`
|
||||
exists(ModExpr me | e = me.getLeftOperand())
|
||||
or
|
||||
// first inductive case: downward AST traversal
|
||||
relevant(e.getParentExpr())
|
||||
or
|
||||
// second inductive case: following variable assignments
|
||||
exists(Variable v | relevant(v.getAnAccess()) | e = v.getAnAssignedExpr())
|
||||
}
|
||||
|
||||
/** Holds if `e` could evaluate to a negative number. */
|
||||
predicate maybeNegative(Expr e) {
|
||||
relevant(e) and
|
||||
if exists(e.getIntValue())
|
||||
then e.getIntValue() < 0
|
||||
else
|
||||
if e instanceof ParExpr
|
||||
then maybeNegative(e.(ParExpr).getExpression())
|
||||
else
|
||||
if e instanceof IncExpr
|
||||
then maybeNegative(e.(IncExpr).getOperand())
|
||||
else
|
||||
if e instanceof VarAccess
|
||||
then maybeNegativeVar(e.(VarAccess).getVariable())
|
||||
else
|
||||
if e instanceof AddExpr
|
||||
then maybeNegative(e.(AddExpr).getAnOperand())
|
||||
else
|
||||
// anything else is considered to possibly be negative
|
||||
any()
|
||||
}
|
||||
|
||||
/** Holds if `v` could be assigned a negative number. */
|
||||
predicate maybeNegativeVar(Variable v) {
|
||||
v.isGlobal()
|
||||
or
|
||||
v.isParameter()
|
||||
or
|
||||
// is v ever assigned a potentially negative value?
|
||||
maybeNegative(v.getAnAssignedExpr())
|
||||
or
|
||||
// is v ever decremented?
|
||||
exists(DecExpr dec | dec.getOperand().getUnderlyingReference() = v.getAnAccess())
|
||||
or
|
||||
// is v ever subject to a compound assignment other than +=, or to
|
||||
// += with potentially negative rhs?
|
||||
exists(CompoundAssignExpr assgn | assgn.getTarget() = v.getAnAccess() |
|
||||
not assgn instanceof AssignAddExpr or
|
||||
maybeNegative(assgn.getRhs())
|
||||
)
|
||||
}
|
||||
|
||||
from Comparison cmp, ModExpr me, int num, string parity
|
||||
where
|
||||
cmp.getAnOperand().stripParens() = me and
|
||||
cmp.getAnOperand().getIntValue() = num and
|
||||
me.getRightOperand().getIntValue() = 2 and
|
||||
maybeNegative(me.getLeftOperand()) and
|
||||
(
|
||||
(cmp instanceof EqExpr or cmp instanceof StrictEqExpr) and
|
||||
num = 1 and
|
||||
parity = "oddness"
|
||||
or
|
||||
(cmp instanceof NEqExpr or cmp instanceof StrictNEqExpr) and
|
||||
num = 1 and
|
||||
parity = "evenness"
|
||||
or
|
||||
cmp instanceof GTExpr and num = 0 and parity = "oddness"
|
||||
)
|
||||
select cmp, "Test for " + parity + " does not take negative numbers into account."
|
||||
@@ -1,56 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
In JavaScript, properties of objects do not have to be declared and can be dynamically added
|
||||
and removed at runtime. Thus, if a property name is misspelled, this is not detected by the
|
||||
compiler, and may lead to an error at runtime. The same problem occurs with misspelled
|
||||
global variables.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This rule flags property names and global variables that are mentioned only once, but where
|
||||
a different capitalization of the same name is used in multiple other places, suggesting a typo.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
Check whether the name has been misspelled. If the name is correct, consider using
|
||||
a <a href="http://www.jslint.com/help.html#properties">JSLint-style</a>
|
||||
<code>/*property ...*/</code> directive to document the existence of this property,
|
||||
or provide an externs file declaring the property.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>
|
||||
The following code snippet contains two uses of the <code>log</code> method, but only
|
||||
one use of the <code>Log</code> method. This suggests that <code>Log</code> may be a typo
|
||||
for <code>log</code>.
|
||||
</p>
|
||||
|
||||
<sample src="examples/HapaxLegomenon.js" />
|
||||
|
||||
<p>
|
||||
If the use of <code>Log</code> is, in fact, a typo, it should be corrected. Otherwise, a
|
||||
<code>properties</code> directive can be introduced to document the fact that both
|
||||
<code>log</code> and <code>Log</code> properties exist:
|
||||
</p>
|
||||
|
||||
<sample src="examples/HapaxLegomenonGood.js" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
|
||||
<li>JSLint: <a href="http://www.jslint.com/help.html#properties">Property</a>.</li>
|
||||
<li>Google Closure Tools: <a href="https://developers.google.com/closure/compiler/docs/api-tutorial3?csw=1#externs">Declaring externs</a>.</li>
|
||||
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,91 +0,0 @@
|
||||
/**
|
||||
* @name Potentially misspelled property or variable name
|
||||
* @description A property or variable is only mentioned once, but there is one with the same name
|
||||
* in different capitalization that is mentioned more than once, suggesting that this
|
||||
* may be a typo.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id js/wrong-capitalization
|
||||
* @tags reliability
|
||||
* @precision low
|
||||
* @deprecated This query is prone to false positives. Deprecated since 1.17.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/** Gets the number of identifiers and string literals that refer to `name`. */
|
||||
int countOccurrences(string name) {
|
||||
(
|
||||
exists(PropAccess pacc | name = pacc.getPropertyName()) or
|
||||
exists(VarAccess acc | name = acc.getName())
|
||||
) and
|
||||
result = strictcount(Expr id |
|
||||
id.(Identifier).getName() = name
|
||||
or
|
||||
// count string literals as well to capture meta-programming
|
||||
id.getStringValue() = name
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access to an undeclared variable or property that is only referenced
|
||||
* once in the entire program.
|
||||
*/
|
||||
abstract class Hapax extends @expr {
|
||||
/** Gets the name of the accessed variable or property. */
|
||||
abstract string getName();
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = this.(Expr).toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An access to a property that is covered neither by a JSLint property declaration
|
||||
* nor by an externs declaration, and that is only mentioned once in the entire program.
|
||||
*/
|
||||
class UndeclaredPropertyAccess extends Hapax, @dotexpr {
|
||||
UndeclaredPropertyAccess() {
|
||||
exists(string name | name = this.(DotExpr).getPropertyName() |
|
||||
countOccurrences(name) = 1 and
|
||||
not exists(JSLintProperties jslpd | jslpd.appliesTo(this) and jslpd.getAProperty() = name) and
|
||||
not exists(ExternalMemberDecl emd | emd.getProperty() = this)
|
||||
)
|
||||
}
|
||||
|
||||
override string getName() { result = this.(DotExpr).getPropertyName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An access to a global variable that is neither declared nor covered by a linter
|
||||
* directive, and that is only mentioned once in the entire program.
|
||||
*/
|
||||
class UndeclaredGlobal extends Hapax, @varaccess {
|
||||
UndeclaredGlobal() {
|
||||
exists(GlobalVariable gv, string name | this = gv.getAnAccess() and name = gv.getName() |
|
||||
countOccurrences(name) = 1 and
|
||||
not exists(Linting::GlobalDeclaration glob | glob.declaresGlobalForAccess(this)) and
|
||||
not exists(gv.getADeclaration())
|
||||
)
|
||||
}
|
||||
|
||||
override string getName() { result = this.(VarAccess).getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of occurrences of `m`, which is the same as `hapax`
|
||||
* except for capitalization, ensuring that it occurs at least twice.
|
||||
*/
|
||||
int candidateSpellingCount(Hapax hapax, string m) {
|
||||
exists(string n | n = hapax.getName() |
|
||||
m.toLowerCase() = n.toLowerCase() and
|
||||
m != n and
|
||||
result = countOccurrences(m) and
|
||||
result > 1
|
||||
)
|
||||
}
|
||||
|
||||
from Hapax hapax, string n, string m
|
||||
where
|
||||
n = hapax.getName() and
|
||||
candidateSpellingCount(hapax, m) = max(candidateSpellingCount(hapax, _))
|
||||
select hapax.(Expr), "'" + n + "' is mentioned only once; it may be a typo for '" + m + "'."
|
||||
Reference in New Issue
Block a user