Python points-to: Split strings into bytes and unicode.

This commit is contained in:
Mark Shannon
2019-04-24 17:44:24 +01:00
parent 48c0cbe51a
commit abf0347fce
5 changed files with 90 additions and 16 deletions

View File

@@ -244,7 +244,7 @@ class FloatObjectInternal extends ConstantObjectInternal, TFloat {
}
class StringObjectInternal extends ConstantObjectInternal, TString {
class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode {
override string toString() {
result = "'" + this.strValue() + "'"
@@ -252,7 +252,8 @@ class StringObjectInternal extends ConstantObjectInternal, TString {
override predicate introduced(ControlFlowNode node, PointsToContext context) {
context.appliesTo(node) and
node.getNode().(StrConst).getText() = this.strValue()
node.getNode().(StrConst).getText() = this.strValue() and
node.getNode().(StrConst).isUnicode()
}
override ObjectInternal getClass() {
@@ -260,7 +261,8 @@ class StringObjectInternal extends ConstantObjectInternal, TString {
}
override Builtin getBuiltin() {
result.(Builtin).strValue() = this.strValue()
result.(Builtin).strValue() = this.strValue() and
result.getClass() = Builtin::special("unicode")
}
override int intValue() {
@@ -268,7 +270,48 @@ class StringObjectInternal extends ConstantObjectInternal, TString {
}
override string strValue() {
this = TString(result)
this = TUnicode(result)
}
override boolean booleanValue() {
this.strValue() = "" and result = false
or
this.strValue() != "" and result = true
}
override int length() {
result = this.strValue().length()
}
}
class BytesObjectInternal extends ConstantObjectInternal, TBytes {
override string toString() {
result = "'" + this.strValue() + "'"
}
override predicate introduced(ControlFlowNode node, PointsToContext context) {
context.appliesTo(node) and
node.getNode().(StrConst).getText() = this.strValue() and
not node.getNode().(StrConst).isUnicode()
}
override ObjectInternal getClass() {
result = TBuiltinClassObject(Builtin::special("bytes"))
}
override Builtin getBuiltin() {
result.(Builtin).strValue() = this.strValue() and
result.getClass() = Builtin::special("bytes")
}
override int intValue() {
none()
}
override string strValue() {
this = TBytes(result)
}
override boolean booleanValue() {

View File

@@ -171,6 +171,7 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject {
or
ModuleAttributes::pointsToAtExit(init, name, ObjectInternal::undefined(), _)
) and
not name = "__init__" and
value = this.submodule(name) and
origin = CfgOrigin::fromObject(value)
)

View File

@@ -72,12 +72,34 @@ newtype TObject =
f = any(FloatLiteral num).getValue()
}
or
TString(string s) {
TUnicode(string s) {
// Any string explicitly mentioned in the source code.
s = any(StrConst str).getText()
exists(StrConst str |
s = str.getText() and
str.isUnicode()
)
or
// Any string from the library put in the DB by the extractor.
s = any(Builtin b).strValue()
exists(Builtin b |
s = b.strValue() and
b.getClass() = Builtin::special("unicode")
)
or
s = "__main__"
}
or
TBytes(string s) {
// Any string explicitly mentioned in the source code.
exists(StrConst str |
s = str.getText() and
not str.isUnicode()
)
or
// Any string from the library put in the DB by the extractor.
exists(Builtin b |
s = b.strValue() and
b.getClass() = Builtin::special("bytes")
)
or
s = "__main__"
}

View File

@@ -177,7 +177,7 @@ cached module PointsToInternal {
}
cached predicate pointsToString(ControlFlowNode f, PointsToContext context, string value) {
exists(StringObjectInternal str |
exists(ObjectInternal str |
PointsToInternal::pointsTo(f, context, str, _) and
str.strValue() = value
)
@@ -494,7 +494,7 @@ cached module PointsToInternal {
/** Implicit "definition" of `__name__` at the start of a module. */
pragma [noinline]
private predicate module_name_points_to(ScopeEntryDefinition def, PointsToContext context, StringObjectInternal value, ControlFlowNode origin) {
private predicate module_name_points_to(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
def.getVariable().getName() = "__name__" and
exists(Module m |
m = def.getScope()
@@ -506,7 +506,7 @@ cached module PointsToInternal {
origin = def.getDefiningNode()
}
private StringObjectInternal module_dunder_name(Module m) {
private ObjectInternal module_dunder_name(Module m) {
exists(string name |
result.strValue() = name |
if m.isPackageInit() then
@@ -685,6 +685,8 @@ module InterModulePointsTo {
PointsToInternal::pointsTo(def.getDefiningNode().(ImportStarNode).getModule(), context, mod, _) |
moduleExportsBoolean(mod, var.getSourceVariable().getName()) = false
or
var.getSourceVariable().getName().charAt(0) = "_"
or
exists(Module m, string name |
m = mod.getSourceModule() and name = var.getSourceVariable().getName() |
not m.declaredInAll(_) and name.charAt(0) = "_"
@@ -768,11 +770,14 @@ module InterModulePointsTo {
}
boolean moduleExportsBoolean(ModuleObjectInternal mod, string name) {
result = pythonModuleExportsBoolean(mod, name)
or
result = packageExportsBoolean(mod, name)
or
result = builtinModuleExportsBoolean(mod, name)
not name.charAt(0) = "_" and
(
result = pythonModuleExportsBoolean(mod, name)
or
result = packageExportsBoolean(mod, name)
or
result = builtinModuleExportsBoolean(mod, name)
)
}
}
@@ -2011,7 +2016,8 @@ module ModuleAttributes {
)
or
/* Retain value held before import */
InterModulePointsTo::moduleExportsBoolean(mod, name) = false and
(InterModulePointsTo::moduleExportsBoolean(mod, name) = false or name.charAt(0) = "_")
and
attributePointsTo(def.getInput(), name, value, origin)
)
}

View File

@@ -11,6 +11,7 @@
| Module test_package | module2 | Module test_package.module2 |
| Module test_package | module3 | Module test_package.module3 |
| Module test_package | module4 | Module test_package.module4 |
| Module test_package | module5 | Module test_package.module5 |
| Module test_package | p | str u'p' |
| Module test_package | q | str u'q' |
| Module test_package | r | str u'r' |
@@ -52,6 +53,7 @@
| Module test_star | module2 | Module test_package.module2 |
| Module test_star | module3 | Module test_package.module3 |
| Module test_star | module4 | Module test_package.module4 |
| Module test_star | module5 | Module test_package.module5 |
| Module test_star | p | str u'p' |
| Module test_star | q | str u'q' |
| Module test_star | r | str u'r' |