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:
Max Schaefer
2019-10-21 14:32:58 +01:00
parent 016c95a69c
commit 55fb86d618
67 changed files with 18 additions and 1615 deletions

View File

@@ -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 &gt; 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>

View File

@@ -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."

View File

@@ -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>

View File

@@ -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 + "'."