Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python: Rename StrConst to StringLiteral #16245

Merged
merged 7 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion python/ql/examples/snippets/raw_string.ql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@

import python

from StrConst s
from StringLiteral s
where s.getPrefix().matches("%r%")
select s
2 changes: 1 addition & 1 deletion python/ql/examples/snippets/singlequotestring.ql
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@

import python

from StrConst s
from StringLiteral s
where s.getPrefix().charAt(_) = "'"
select s
2 changes: 1 addition & 1 deletion python/ql/lib/analysis/DefinitionTracking.qll
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ private predicate sets_attribute(ArgumentRefinement def, string name) {
call = def.getDefiningNode() and
call.getFunction().refersTo(Object::builtin("setattr")) and
def.getInput().getAUse() = call.getArg(0) and
call.getArg(1).getNode().(StrConst).getText() = name
call.getArg(1).getNode().(StringLiteral).getText() = name
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
category: deprecated
---

- Renamed the `StrConst` class to `StringLiteral`, for greater consistency with other languages. The `StrConst` and `Str` classes are now deprecated and will be removed in a future release.
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ module Hashes {
}

override string getName() {
result = super.normalizeName(this.asExpr().(StrConst).getText())
result = super.normalizeName(this.asExpr().(StringLiteral).getText())
or
// if not a known/static string, assume from an outside source and the algorithm is UNKNOWN
not this.asExpr() instanceof StrConst and result = unknownAlgorithm()
not this.asExpr() instanceof StringLiteral and result = unknownAlgorithm()
}
}

Expand All @@ -49,10 +49,10 @@ module Hashes {
}

override string getName() {
result = super.normalizeName(this.asExpr().(StrConst).getText())
result = super.normalizeName(this.asExpr().(StringLiteral).getText())
or
// if not a known/static string, assume from an outside source and the algorithm is UNKNOWN
not this.asExpr() instanceof StrConst and result = unknownAlgorithm()
not this.asExpr() instanceof StringLiteral and result = unknownAlgorithm()
}
}

Expand Down Expand Up @@ -88,9 +88,9 @@ module Hashes {
// Name is a string constant or consider the name unknown
// NOTE: we are excluding hmac.new and hmac.HMAC constructor calls so we are expecting
// a string or an outside configuration only
result = super.normalizeName(this.asExpr().(StrConst).getText())
result = super.normalizeName(this.asExpr().(StringLiteral).getText())
or
not this.asExpr() instanceof StrConst and
not this.asExpr() instanceof StringLiteral and
result = unknownAlgorithm()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ module Hashes {
then result = super.normalizeName("MD5")
else (
// Else get the string name, if its a string constant, or UNKNOWN if otherwise
result = super.normalizeName(this.asExpr().(StrConst).getText())
result = super.normalizeName(this.asExpr().(StringLiteral).getText())
or
not this.asExpr() instanceof StrConst and result = unknownAlgorithm()
not this.asExpr() instanceof StringLiteral and result = unknownAlgorithm()
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/semmle/python/ApiGraphs.qll
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ module API {
*/
Node getSubscript(string key) {
exists(API::Node index | result = this.getSubscriptAt(index) |
key = index.getAValueReachingSink().asExpr().(PY::StrConst).getText()
key = index.getAValueReachingSink().asExpr().(PY::StringLiteral).getText()
)
}

Expand Down
4 changes: 2 additions & 2 deletions python/ql/lib/semmle/python/Concepts.qll
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ module Http {

/** Gets the URL pattern for this route, if it can be statically determined. */
string getUrlPattern() {
exists(StrConst str |
exists(StringLiteral str |
this.getUrlPatternArg().getALocalSource() = DataFlow::exprNode(str) and
result = str.getText()
)
Expand Down Expand Up @@ -983,7 +983,7 @@ module Http {

/** Gets the mimetype of this HTTP response, if it can be statically determined. */
string getMimetype() {
exists(StrConst str |
exists(StringLiteral str |
this.getMimetypeOrContentTypeArg().getALocalSource() = DataFlow::exprNode(str) and
result = str.getText().splitAt(";", 0)
)
Expand Down
25 changes: 17 additions & 8 deletions python/ql/lib/semmle/python/Exprs.qll
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ class Call extends Call_ {
string getANamedArgumentName() {
result = this.getAKeyword().getArg()
or
result = this.getKwargs().(Dict).getAKey().(StrConst).getText()
result = this.getKwargs().(Dict).getAKey().(StringLiteral).getText()
}

/** Gets the positional argument count of this call, provided there is no more than one tuple (*) argument. */
Expand Down Expand Up @@ -299,7 +299,7 @@ class Repr extends Repr_ {
* A bytes constant, such as `b'ascii'`. Note that unadorned string constants such as
* `"hello"` are treated as Bytes for Python2, but Unicode for Python3.
*/
class Bytes extends StrConst {
class Bytes extends StringLiteral {
/* syntax: b"hello" */
Bytes() { not this.isUnicode() }

Expand Down Expand Up @@ -446,7 +446,7 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
* A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as
* "hello" are treated as Bytes for Python2, but Unicode for Python3.
*/
class Unicode extends StrConst {
class Unicode extends StringLiteral {
/* syntax: "hello" */
Unicode() { this.isUnicode() }

Expand Down Expand Up @@ -599,7 +599,7 @@ class Slice extends Slice_ {
/**
* Returns all string prefixes in the database that are explicitly marked as Unicode strings.
*
* Helper predicate for `StrConst::isUnicode`.
* Helper predicate for `StringLiteral::isUnicode`.
*/
pragma[nomagic]
private string unicode_prefix() {
Expand All @@ -610,20 +610,27 @@ private string unicode_prefix() {
/**
* Returns all string prefixes in the database that are _not_ explicitly marked as bytestrings.
*
* Helper predicate for `StrConst::isUnicode`.
* Helper predicate for `StringLiteral::isUnicode`.
*/
pragma[nomagic]
private string non_byte_prefix() {
result = any(Str_ s).getPrefix() and
not result.charAt(_) in ["b", "B"]
}

/** A string constant. This is a placeholder class -- use `StrConst` instead. */
class Str = StrConst;
/** DEPRECATED. Use `StringLiteral` instead. */
deprecated class Str = StringLiteral;

/** DEPRECATED. Use `StringLiteral` instead. */
deprecated class StrConst = StringLiteral;

/** A string constant. */
class StrConst extends Str_, ImmutableLiteral {
class StringLiteral extends Str_, ImmutableLiteral {
/* syntax: "hello" */
/**
* Holds if this string is a unicode string, either by default (e.g. if Python 3), or with an
* explicit prefix.
*/
predicate isUnicode() {
this.getPrefix() = unicode_prefix()
or
Expand Down Expand Up @@ -652,6 +659,8 @@ class StrConst extends Str_, ImmutableLiteral {
}

override Object getLiteralObject() { none() }

override string toString() { result = "StringLiteral" }
}

private predicate name_consts(Name_ n, string id) {
Expand Down
4 changes: 2 additions & 2 deletions python/ql/lib/semmle/python/Files.qll
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class File extends Container, Impl::File {
exists(Stmt s | s.getLocation().getFile() = this)
or
// The file contains the usual `if __name__ == '__main__':` construction
exists(If i, Name name, StrConst main, Cmpop op |
exists(If i, Name name, StringLiteral main, Cmpop op |
i.getScope().(Module).getFile() = this and
op instanceof Eq and
i.getTest().(Compare).compares(name, op, main) and
Expand Down Expand Up @@ -123,7 +123,7 @@ private predicate occupied_line(File f, int n) {
exists(Location l | l.getFile() = f |
l.getStartLine() = n
or
exists(StrConst s | s.getLocation() = l | n in [l.getStartLine() .. l.getEndLine()])
exists(StringLiteral s | s.getLocation() = l | n in [l.getStartLine() .. l.getEndLine()])
)
}

Expand Down
4 changes: 2 additions & 2 deletions python/ql/lib/semmle/python/Module.qll
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ class Module extends Module_, Scope, AstNode {
a.getScope() = this and
all.getId() = "__all__" and
(
a.getValue().(List).getAnElt().(StrConst).getText() = name
a.getValue().(List).getAnElt().(StringLiteral).getText() = name
or
a.getValue().(Tuple).getAnElt().(StrConst).getText() = name
a.getValue().(Tuple).getAnElt().(StringLiteral).getText() = name
)
)
}
Expand Down
8 changes: 4 additions & 4 deletions python/ql/lib/semmle/python/PrintAst.qll
Original file line number Diff line number Diff line change
Expand Up @@ -423,13 +423,13 @@ class ParameterNode extends AstElementNode {
}

/**
* A print node for a `StrConst`.
* A print node for a `StringLiteral`.
*
* The string has a child, if the child is used as a regular expression,
* which is the root of the regular expression.
*/
class StrConstNode extends AstElementNode {
override StrConst element;
class StringLiteralNode extends AstElementNode {
override StringLiteral element;
}

/**
Expand Down Expand Up @@ -599,7 +599,7 @@ private module PrettyPrinting {
or
result = "class " + a.(Class).getName()
or
result = a.(StrConst).getText()
result = a.(StringLiteral).getText()
or
result = "yield " + a.(Yield).getValue()
or
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/semmle/python/Scope.qll
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class Scope extends Scope_ {
string getName() { py_strs(result, this, 0) }

/** Gets the docstring for this scope */
StrConst getDocString() { result = this.getStmt(0).(ExprStmt).getValue() }
StringLiteral getDocString() { result = this.getStmt(0).(ExprStmt).getValue() }

/** Gets the entry point into this Scope's control flow graph */
ControlFlowNode getEntryNode() { py_scope_flow(result, this, -1) }
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/semmle/python/Stmts.qll
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ class If extends If_ {

/** Whether this if statement takes the form `if __name__ == "__main__":` */
predicate isNameEqMain() {
exists(StrConst m, Name n, Compare c |
exists(StringLiteral m, Name n, Compare c |
this.getTest() = c and
c.getOp(0) instanceof Eq and
(
Expand Down
4 changes: 2 additions & 2 deletions python/ql/lib/semmle/python/dataflow/new/BarrierGuards.qll
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ private import semmle.python.dataflow.new.DataFlow

private predicate stringConstCompare(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
exists(CompareNode cn | cn = g |
exists(StrConst str_const, Cmpop op |
exists(StringLiteral str_const, Cmpop op |
op = any(Eq eq) and branch = true
or
op = any(NotEq ne) and branch = false
Expand All @@ -21,7 +21,7 @@ private predicate stringConstCompare(DataFlow::GuardNode g, ControlFlowNode node
op = any(NotIn ni) and branch = false
|
forall(ControlFlowNode elem | elem = str_const_iterable.getAnElement() |
elem.getNode() instanceof StrConst
elem.getNode() instanceof StringLiteral
) and
cn.operands(node, op, str_const_iterable)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ private module SensitiveDataModeling {
// Note: If this is implemented with type-tracking, we will get cross-talk as
// illustrated in python/ql/test/experimental/dataflow/sensitive-data/test.py
exists(DataFlow::LocalSourceNode source |
source.asExpr().(StrConst).getText() = sensitiveString(classification) and
source.asExpr().(StringLiteral).getText() = sensitiveString(classification) and
source.flowsTo(result)
)
}
Expand Down Expand Up @@ -173,8 +173,8 @@ private module SensitiveDataModeling {
}

pragma[nomagic]
private string sensitiveStrConstCandidate() {
result = any(StrConst s | not s.isDocString()).getText() and
private string sensitiveStringLiteralCandidate() {
result = any(StringLiteral s | not s.isDocString()).getText() and
not result.regexpMatch(notSensitiveRegexp())
}

Expand Down Expand Up @@ -217,7 +217,7 @@ private module SensitiveDataModeling {
result in [
sensitiveNameCandidate(), sensitiveAttributeNameCandidate(),
sensitiveParameterNameCandidate(), sensitiveFunctionNameCandidate(),
sensitiveStrConstCandidate()
sensitiveStringLiteralCandidate()
]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ abstract class AttrRef extends Node {
or
exists(LocalSourceNode nodeFrom |
nodeFrom.flowsTo(this.getAttributeNameExpr()) and
attrName = nodeFrom.(CfgNode).getNode().getNode().(StrConst).getText()
attrName = nodeFrom.(CfgNode).getNode().getNode().(StringLiteral).getText()
)
}

Expand Down Expand Up @@ -178,7 +178,7 @@ private class SetAttrCallAsAttrWrite extends AttrWrite, CfgNode {
override ExprNode getAttributeNameExpr() { result.asCfgNode() = node.getName() }

override string getAttributeName() {
result = this.getAttributeNameExpr().(CfgNode).getNode().getNode().(StrConst).getText()
result = this.getAttributeNameExpr().(CfgNode).getNode().getNode().(StringLiteral).getText()
}
}

Expand Down Expand Up @@ -254,7 +254,7 @@ private class GetAttrCallAsAttrRead extends AttrRead, CfgNode {
override ExprNode getAttributeNameExpr() { result.asCfgNode() = node.getName() }

override string getAttributeName() {
result = this.getAttributeNameExpr().(CfgNode).getNode().getNode().(StrConst).getText()
result = this.getAttributeNameExpr().(CfgNode).getNode().getNode().(StringLiteral).getText()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ predicate dictStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeT
exists(KeyValuePair item |
item = nodeTo.asCfgNode().(DictNode).getNode().(Dict).getAnItem() and
nodeFrom.getNode().getNode() = item.getValue() and
c.getKey() = item.getKey().(StrConst).getS()
c.getKey() = item.getKey().(StringLiteral).getS()
)
}

Expand All @@ -829,13 +829,13 @@ private predicate moreDictStoreSteps(CfgNode nodeFrom, DictionaryElementContent
exists(SubscriptNode subscript |
nodeTo.(PostUpdateNode).getPreUpdateNode().asCfgNode() = subscript.getObject() and
nodeFrom.asCfgNode() = subscript.(DefinitionNode).getValue() and
c.getKey() = subscript.getIndex().getNode().(StrConst).getText()
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
)
or
// see https://docs.python.org/3.10/library/stdtypes.html#dict.setdefault
exists(MethodCallNode call |
call.calls(nodeTo.(PostUpdateNode).getPreUpdateNode(), "setdefault") and
call.getArg(0).asExpr().(StrConst).getText() = c.getKey() and
call.getArg(0).asExpr().(StringLiteral).getText() = c.getKey() and
nodeFrom = call.getArg(1)
)
}
Expand All @@ -844,7 +844,7 @@ predicate dictClearStep(Node node, DictionaryElementContent c) {
exists(SubscriptNode subscript |
subscript instanceof DefinitionNode and
node.asCfgNode() = subscript.getObject() and
c.getKey() = subscript.getIndex().getNode().(StrConst).getText()
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
)
}

Expand Down Expand Up @@ -954,7 +954,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
nodeTo.getNode().(SubscriptNode).getIndex().getNode().(IntegerLiteral).getValue()
or
c.(DictionaryElementContent).getKey() =
nodeTo.getNode().(SubscriptNode).getIndex().getNode().(StrConst).getS()
nodeTo.getNode().(SubscriptNode).getIndex().getNode().(StringLiteral).getS()
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -606,17 +606,18 @@ newtype TContent =
/** An element of a dictionary under a specific key. */
TDictionaryElementContent(string key) {
// {"key": ...}
key = any(KeyValuePair kvp).getKey().(StrConst).getText()
key = any(KeyValuePair kvp).getKey().(StringLiteral).getText()
or
// func(key=...)
key = any(Keyword kw).getArg()
or
// d["key"] = ...
key = any(SubscriptNode sub | sub.isStore() | sub.getIndex().getNode().(StrConst).getText())
key =
any(SubscriptNode sub | sub.isStore() | sub.getIndex().getNode().(StringLiteral).getText())
or
// d.setdefault("key", ...)
exists(CallNode call | call.getFunction().(AttrNode).getName() = "setdefault" |
key = call.getArg(0).getNode().(StrConst).getText()
key = call.getArg(0).getNode().(StringLiteral).getText()
)
} or
/** An element of a dictionary under any key. */
Expand Down
Loading
Loading