Adds some debugging changes.

This commit is contained in:
Rebecca Valentine
2020-02-12 19:29:42 -08:00
parent 178acc85b9
commit 3ce250b2cf
2 changed files with 64 additions and 3 deletions

View File

@@ -13,7 +13,37 @@
import python
import semmle.python.strings
/* modernized query
from Expr e, ClassValue t
where exists(BinaryExpr b | b.getOp() instanceof Mod and format_string(b.getLeft()) and e = b.getRight() and
mapping_format(b.getLeft()) and e.pointsTo(_, t, _) and not t.isMapping())
select e, "Right hand side of a % operator must be a mapping, not class $@.", t, t.getName()
select e, "Right hand side of a % operator must be a mapping, not class $@.", t, t.getName()
//*/
/* original query
from Expr e, ClassObject t
where exists(BinaryExpr b | b.getOp() instanceof Mod and format_string(b.getLeft()) and e = b.getRight() and
mapping_format(b.getLeft()) and e.refersTo(_, t, _) and not t.isMapping())
select e, "Right hand side of a % operator must be a mapping, not class $@.", t, t.getName()
//*/
//* debug query
from Expr e, ClassValue t, string s
where any()
and exists(BinaryExpr b | any()
and b.getOp() instanceof Mod
and format_string(b.getLeft())
and e = b.getRight()
and mapping_format(b.getLeft())
and e.pointsTo().getClass() = t
//and not t.isMapping()
)
and if t.hasAttribute("__getitem__") then s = "yes" else s = "no"
select
e
, "Right hand side of a % operator must be a mapping, not class $@."
, t
, t.getName()
, s
, s
//*/

View File

@@ -403,14 +403,45 @@ class ClassValue extends Value {
this.hasAttribute("__getitem__")
}
/** Holds if this class is a container(). That is, does it have a __getitem__ method.*/
predicate isContainer() {
exists(this.lookup("__getitem__"))
}
/** Holds if this class is probably a sequence. */
predicate isSequence() {
/* To determine whether something is a sequence or a mapping is not entirely clear,
* so we need to guess a bit.
*/
this.getASuperType() = ClassValue::tupleType()
or
this.getASuperType() = ClassValue::list()
or
this.getASuperType() = ClassValue::rangeType()
or
this.getASuperType() = ClassValue::bytes()
or
this.getASuperType() = ClassValue::unicode()
or
/* Does this inherit from abc.Sequence? */
this.getASuperType().getName() = "Sequence"
or
/* Does it have an index or __reversed__ method? */
this.isContainer() and
(
this.hasAttribute("index") or
this.hasAttribute("__reversed__")
)
}
/** Holds if this class is a mapping.
*
* This is an attempt to translate ClassObject::isMapping()
*/
predicate isMapping() {
exists(this.attr("__getitem__"))
this.hasAttribute("__getitem__")
and
not this instanceof SequenceValue
not this.isSequence()
}
/** Holds if this class is a descriptor. */