mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
C++/C#/Java/JavaScript/Python: Autoformat set literals.
This commit is contained in:
@@ -86,9 +86,11 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
||||
object = call.getFunction().(AttrNode).getObject(method_name)
|
||||
|
|
||||
nodeFrom.getNode() = object and
|
||||
method_name in ["capitalize", "casefold", "center", "expandtabs", "format", "format_map",
|
||||
"join", "ljust", "lstrip", "lower", "replace", "rjust", "rstrip", "strip", "swapcase",
|
||||
"title", "upper", "zfill", "encode", "decode"]
|
||||
method_name in [
|
||||
"capitalize", "casefold", "center", "expandtabs", "format", "format_map", "join", "ljust",
|
||||
"lstrip", "lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper",
|
||||
"zfill", "encode", "decode"
|
||||
]
|
||||
or
|
||||
method_name = "replace" and
|
||||
nodeFrom.getNode() = call.getArg(1)
|
||||
@@ -156,8 +158,9 @@ predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) {
|
||||
or
|
||||
// constructor call
|
||||
exists(CallNode call | call = nodeTo.asCfgNode() |
|
||||
call.getFunction().(NameNode).getId() in ["list", "set", "frozenset", "dict", "defaultdict",
|
||||
"tuple"] and
|
||||
call.getFunction().(NameNode).getId() in [
|
||||
"list", "set", "frozenset", "dict", "defaultdict", "tuple"
|
||||
] and
|
||||
call.getArg(0) = nodeFrom.getNode()
|
||||
)
|
||||
or
|
||||
@@ -169,11 +172,13 @@ predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) {
|
||||
or
|
||||
// methods
|
||||
exists(CallNode call, string name | call = nodeTo.asCfgNode() |
|
||||
name in ["copy",
|
||||
// general
|
||||
"pop",
|
||||
// dict
|
||||
"values", "items", "get", "popitem"] and
|
||||
name in [
|
||||
"copy",
|
||||
// general
|
||||
"pop",
|
||||
// dict
|
||||
"values", "items", "get", "popitem"
|
||||
] and
|
||||
call.getFunction().(AttrNode).getObject(name) = nodeFrom.asCfgNode()
|
||||
)
|
||||
or
|
||||
|
||||
@@ -259,8 +259,9 @@ private module Django {
|
||||
|
||||
ObjectsAnnotate() {
|
||||
node.getFunction() = django::db::models::objects_attr("annotate").asCfgNode() and
|
||||
django::db::models::expressions::RawSQL::instance(sql).asCfgNode() in [node.getArg(_),
|
||||
node.getArgByName(_)]
|
||||
django::db::models::expressions::RawSQL::instance(sql).asCfgNode() in [
|
||||
node.getArg(_), node.getArgByName(_)
|
||||
]
|
||||
}
|
||||
|
||||
override DataFlow::Node getSql() { result.asCfgNode() = sql }
|
||||
@@ -423,18 +424,19 @@ private module Django {
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node http_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["request",
|
||||
// request
|
||||
"HttpRequest",
|
||||
// response
|
||||
"response", "HttpResponse",
|
||||
// HttpResponse subclasses
|
||||
"HttpResponseRedirect", "HttpResponsePermanentRedirect", "HttpResponseNotModified",
|
||||
"HttpResponseBadRequest", "HttpResponseNotFound", "HttpResponseForbidden",
|
||||
"HttpResponseNotAllowed", "HttpResponseGone", "HttpResponseServerError",
|
||||
"JsonResponse",
|
||||
// HttpResponse-like classes
|
||||
"StreamingHttpResponse", "FileResponse"] and
|
||||
attr_name in [
|
||||
"request",
|
||||
// request
|
||||
"HttpRequest",
|
||||
// response
|
||||
"response", "HttpResponse",
|
||||
// HttpResponse subclasses
|
||||
"HttpResponseRedirect", "HttpResponsePermanentRedirect", "HttpResponseNotModified",
|
||||
"HttpResponseBadRequest", "HttpResponseNotFound", "HttpResponseForbidden",
|
||||
"HttpResponseNotAllowed", "HttpResponseGone", "HttpResponseServerError", "JsonResponse",
|
||||
// HttpResponse-like classes
|
||||
"StreamingHttpResponse", "FileResponse"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("django.http" + "." + attr_name)
|
||||
@@ -576,14 +578,16 @@ private module Django {
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node response_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["HttpResponse",
|
||||
// HttpResponse subclasses
|
||||
"HttpResponseRedirect", "HttpResponsePermanentRedirect", "HttpResponseNotModified",
|
||||
"HttpResponseBadRequest", "HttpResponseNotFound", "HttpResponseForbidden",
|
||||
"HttpResponseNotAllowed", "HttpResponseGone", "HttpResponseServerError",
|
||||
"JsonResponse",
|
||||
// HttpResponse-like classes
|
||||
"StreamingHttpResponse", "FileResponse"] and
|
||||
attr_name in [
|
||||
"HttpResponse",
|
||||
// HttpResponse subclasses
|
||||
"HttpResponseRedirect", "HttpResponsePermanentRedirect", "HttpResponseNotModified",
|
||||
"HttpResponseBadRequest", "HttpResponseNotFound", "HttpResponseForbidden",
|
||||
"HttpResponseNotAllowed", "HttpResponseGone", "HttpResponseServerError",
|
||||
"JsonResponse",
|
||||
// HttpResponse-like classes
|
||||
"StreamingHttpResponse", "FileResponse"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("django.http.response" + "." + attr_name)
|
||||
@@ -1704,25 +1708,27 @@ private module Django {
|
||||
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
nodeFrom = django::http::request::HttpRequest::instance() and
|
||||
exists(DataFlow::AttrRead read | nodeTo = read and read.getObject() = nodeFrom |
|
||||
read.getAttributeName() in ["body",
|
||||
// str / bytes
|
||||
"path", "path_info", "method", "encoding", "content_type",
|
||||
// django.http.QueryDict
|
||||
// TODO: Model QueryDict
|
||||
"GET", "POST",
|
||||
// dict[str, str]
|
||||
"content_params", "COOKIES",
|
||||
// dict[str, Any]
|
||||
"META",
|
||||
// HttpHeaders (case insensitive dict-like)
|
||||
"headers",
|
||||
// MultiValueDict[str, UploadedFile]
|
||||
// TODO: Model MultiValueDict
|
||||
// TODO: Model UploadedFile
|
||||
"FILES",
|
||||
// django.urls.ResolverMatch
|
||||
// TODO: Model ResolverMatch
|
||||
"resolver_match"]
|
||||
read.getAttributeName() in [
|
||||
"body",
|
||||
// str / bytes
|
||||
"path", "path_info", "method", "encoding", "content_type",
|
||||
// django.http.QueryDict
|
||||
// TODO: Model QueryDict
|
||||
"GET", "POST",
|
||||
// dict[str, str]
|
||||
"content_params", "COOKIES",
|
||||
// dict[str, Any]
|
||||
"META",
|
||||
// HttpHeaders (case insensitive dict-like)
|
||||
"headers",
|
||||
// MultiValueDict[str, UploadedFile]
|
||||
// TODO: Model MultiValueDict
|
||||
// TODO: Model UploadedFile
|
||||
"FILES",
|
||||
// django.urls.ResolverMatch
|
||||
// TODO: Model ResolverMatch
|
||||
"resolver_match"
|
||||
]
|
||||
// TODO: Handle calls to methods
|
||||
// TODO: Handle that a HttpRequest is iterable
|
||||
)
|
||||
|
||||
@@ -168,13 +168,15 @@ private module FabricV2 {
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node fabric_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["connection",
|
||||
// connection.py
|
||||
"Connection",
|
||||
// group.py
|
||||
"group", "SerialGroup", "ThreadingGroup",
|
||||
// tasks.py
|
||||
"tasks", "task"] and
|
||||
attr_name in [
|
||||
"connection",
|
||||
// connection.py
|
||||
"Connection",
|
||||
// group.py
|
||||
"group", "SerialGroup", "ThreadingGroup",
|
||||
// tasks.py
|
||||
"tasks", "task"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("fabric" + "." + attr_name)
|
||||
|
||||
@@ -388,40 +388,42 @@ private module FlaskModel {
|
||||
exists(AttrNode attr |
|
||||
this.asCfgNode() = attr and attr.getObject(attr_name) = flask::request().asCfgNode()
|
||||
|
|
||||
attr_name in ["path",
|
||||
// str
|
||||
"full_path", "base_url", "url", "access_control_request_method", "content_encoding",
|
||||
"content_md5", "content_type", "data", "method", "mimetype", "origin", "query_string",
|
||||
"referrer", "remote_addr", "remote_user", "user_agent",
|
||||
// dict
|
||||
"environ", "cookies", "mimetype_params", "view_args",
|
||||
// json
|
||||
"json",
|
||||
// List[str]
|
||||
"access_route",
|
||||
// file-like
|
||||
"stream", "input_stream",
|
||||
// MultiDict[str, str]
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.MultiDict
|
||||
"args", "values", "form",
|
||||
// MultiDict[str, FileStorage]
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.FileStorage
|
||||
// TODO: FileStorage needs extra taint steps
|
||||
"files",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.HeaderSet
|
||||
"access_control_request_headers", "pragma",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Accept
|
||||
// TODO: Kinda badly modeled for now -- has type List[Tuple[value, quality]], and some extra methods
|
||||
"accept_charsets", "accept_encodings", "accept_languages", "accept_mimetypes",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Authorization
|
||||
// TODO: dict subclass with extra attributes like `username` and `password`
|
||||
"authorization",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.RequestCacheControl
|
||||
// TODO: has attributes like `no_cache`, and `to_header` method (actually, many of these models do)
|
||||
"cache_control",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Headers
|
||||
// TODO: dict-like with wsgiref.headers.Header compatibility methods
|
||||
"headers"]
|
||||
attr_name in [
|
||||
"path",
|
||||
// str
|
||||
"full_path", "base_url", "url", "access_control_request_method", "content_encoding",
|
||||
"content_md5", "content_type", "data", "method", "mimetype", "origin", "query_string",
|
||||
"referrer", "remote_addr", "remote_user", "user_agent",
|
||||
// dict
|
||||
"environ", "cookies", "mimetype_params", "view_args",
|
||||
// json
|
||||
"json",
|
||||
// List[str]
|
||||
"access_route",
|
||||
// file-like
|
||||
"stream", "input_stream",
|
||||
// MultiDict[str, str]
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.MultiDict
|
||||
"args", "values", "form",
|
||||
// MultiDict[str, FileStorage]
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.FileStorage
|
||||
// TODO: FileStorage needs extra taint steps
|
||||
"files",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.HeaderSet
|
||||
"access_control_request_headers", "pragma",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Accept
|
||||
// TODO: Kinda badly modeled for now -- has type List[Tuple[value, quality]], and some extra methods
|
||||
"accept_charsets", "accept_encodings", "accept_languages", "accept_mimetypes",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Authorization
|
||||
// TODO: dict subclass with extra attributes like `username` and `password`
|
||||
"authorization",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.RequestCacheControl
|
||||
// TODO: has attributes like `no_cache`, and `to_header` method (actually, many of these models do)
|
||||
"cache_control",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Headers
|
||||
// TODO: dict-like with wsgiref.headers.Header compatibility methods
|
||||
"headers"
|
||||
]
|
||||
)
|
||||
or
|
||||
// methods (needs special handling to track bound-methods -- see `FlaskRequestMethodCallsAdditionalTaintStep` below)
|
||||
|
||||
@@ -32,14 +32,16 @@ private module Stdlib {
|
||||
* For example, using `attr_name = "system"` will get all uses of `os.system`.
|
||||
*/
|
||||
private DataFlow::Node os_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["system", "popen", "popen2", "popen3", "popen4",
|
||||
// exec
|
||||
"execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe",
|
||||
// spawn
|
||||
"spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", "spawnvpe",
|
||||
"posix_spawn", "posix_spawnp",
|
||||
// modules
|
||||
"path"] and
|
||||
attr_name in [
|
||||
"system", "popen", "popen2", "popen3", "popen4",
|
||||
// exec
|
||||
"execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe",
|
||||
// spawn
|
||||
"spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", "spawnvpe",
|
||||
"posix_spawn", "posix_spawnp",
|
||||
// modules
|
||||
"path"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("os." + attr_name)
|
||||
@@ -218,8 +220,9 @@ private module Stdlib {
|
||||
|
||||
OsSpawnCall() {
|
||||
exists(string name |
|
||||
name in ["spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp",
|
||||
"spawnvpe"] and
|
||||
name in [
|
||||
"spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", "spawnvpe"
|
||||
] and
|
||||
node.getFunction() = os_attr(name).asCfgNode()
|
||||
)
|
||||
}
|
||||
@@ -505,9 +508,11 @@ private module Stdlib {
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node popen2_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["popen2", "popen3", "popen4",
|
||||
// classes
|
||||
"Popen3", "Popen4"] and
|
||||
attr_name in [
|
||||
"popen2", "popen3", "popen4",
|
||||
// classes
|
||||
"Popen3", "Popen4"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("popen2." + attr_name)
|
||||
@@ -772,10 +777,12 @@ DataFlow::Node base64() { result = base64(DataFlow::TypeTracker::end()) }
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node base64_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["b64encode", "b64decode", "standard_b64encode", "standard_b64decode",
|
||||
"urlsafe_b64encode", "urlsafe_b64decode", "b32encode", "b32decode", "b16encode",
|
||||
"b16decode", "encodestring", "decodestring", "a85encode", "a85decode", "b85encode",
|
||||
"b85decode", "encodebytes", "decodebytes"] and
|
||||
attr_name in [
|
||||
"b64encode", "b64decode", "standard_b64encode", "standard_b64decode", "urlsafe_b64encode",
|
||||
"urlsafe_b64decode", "b32encode", "b32decode", "b16encode", "b16decode", "encodestring",
|
||||
"decodestring", "a85encode", "a85decode", "b85encode", "b85decode", "encodebytes",
|
||||
"decodebytes"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("base64" + "." + attr_name)
|
||||
@@ -815,8 +822,10 @@ private class Base64EncodeCall extends Encoding::Range, DataFlow::CfgNode {
|
||||
|
||||
Base64EncodeCall() {
|
||||
exists(string name |
|
||||
name in ["b64encode", "standard_b64encode", "urlsafe_b64encode", "b32encode", "b16encode",
|
||||
"encodestring", "a85encode", "b85encode", "encodebytes"] and
|
||||
name in [
|
||||
"b64encode", "standard_b64encode", "urlsafe_b64encode", "b32encode", "b16encode",
|
||||
"encodestring", "a85encode", "b85encode", "encodebytes"
|
||||
] and
|
||||
node.getFunction() = base64_attr(name).asCfgNode()
|
||||
)
|
||||
}
|
||||
@@ -827,7 +836,9 @@ private class Base64EncodeCall extends Encoding::Range, DataFlow::CfgNode {
|
||||
|
||||
override string getFormat() {
|
||||
exists(string name | node.getFunction() = base64_attr(name).asCfgNode() |
|
||||
name in ["b64encode", "standard_b64encode", "urlsafe_b64encode", "encodestring", "encodebytes"] and
|
||||
name in [
|
||||
"b64encode", "standard_b64encode", "urlsafe_b64encode", "encodestring", "encodebytes"
|
||||
] and
|
||||
result = "Base64"
|
||||
or
|
||||
name = "b32encode" and result = "Base32"
|
||||
@@ -847,8 +858,10 @@ private class Base64DecodeCall extends Decoding::Range, DataFlow::CfgNode {
|
||||
|
||||
Base64DecodeCall() {
|
||||
exists(string name |
|
||||
name in ["b64decode", "standard_b64decode", "urlsafe_b64decode", "b32decode", "b16decode",
|
||||
"decodestring", "a85decode", "b85decode", "decodebytes"] and
|
||||
name in [
|
||||
"b64decode", "standard_b64decode", "urlsafe_b64decode", "b32decode", "b16decode",
|
||||
"decodestring", "a85decode", "b85decode", "decodebytes"
|
||||
] and
|
||||
node.getFunction() = base64_attr(name).asCfgNode()
|
||||
)
|
||||
}
|
||||
@@ -861,7 +874,9 @@ private class Base64DecodeCall extends Decoding::Range, DataFlow::CfgNode {
|
||||
|
||||
override string getFormat() {
|
||||
exists(string name | node.getFunction() = base64_attr(name).asCfgNode() |
|
||||
name in ["b64decode", "standard_b64decode", "urlsafe_b64decode", "decodestring", "decodebytes"] and
|
||||
name in [
|
||||
"b64decode", "standard_b64decode", "urlsafe_b64decode", "decodestring", "decodebytes"
|
||||
] and
|
||||
result = "Base64"
|
||||
or
|
||||
name = "b32decode" and result = "Base32"
|
||||
|
||||
@@ -115,15 +115,17 @@ module Werkzeug {
|
||||
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
nodeFrom = werkzeug::datastructures::FileStorage::instance() and
|
||||
exists(DataFlow::AttrRead read | nodeTo = read |
|
||||
read.getAttributeName() in ["filename",
|
||||
// str
|
||||
"name", "content_type", "mimetype",
|
||||
// file-like
|
||||
"stream",
|
||||
// TODO: werkzeug.datastructures.Headers
|
||||
"headers",
|
||||
// dict[str, str]
|
||||
"mimetype_params"] and
|
||||
read.getAttributeName() in [
|
||||
"filename",
|
||||
// str
|
||||
"name", "content_type", "mimetype",
|
||||
// file-like
|
||||
"stream",
|
||||
// TODO: werkzeug.datastructures.Headers
|
||||
"headers",
|
||||
// dict[str, str]
|
||||
"mimetype_params"
|
||||
] and
|
||||
read.getObject() = nodeFrom
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,11 +8,12 @@ abstract class StringKind extends TaintKind {
|
||||
StringKind() { this = this }
|
||||
|
||||
override TaintKind getTaintOfMethodResult(string name) {
|
||||
name in ["capitalize", "casefold", "center", "expandtabs", "format", "format_map", "ljust",
|
||||
"lstrip", "lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper",
|
||||
"zfill",
|
||||
/* encode/decode is technically not correct, but close enough */
|
||||
"encode", "decode"] and
|
||||
name in [
|
||||
"capitalize", "casefold", "center", "expandtabs", "format", "format_map", "ljust", "lstrip",
|
||||
"lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper", "zfill",
|
||||
/* encode/decode is technically not correct, but close enough */
|
||||
"encode", "decode"
|
||||
] and
|
||||
result = this
|
||||
or
|
||||
name in ["partition", "rpartition", "rsplit", "split", "splitlines"] and
|
||||
|
||||
@@ -6,8 +6,9 @@ class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
|
||||
TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.(DataFlow::CfgNode).getNode().(NameNode).getId() in ["TAINTED_STRING", "TAINTED_BYTES",
|
||||
"TAINTED_LIST", "TAINTED_DICT"]
|
||||
source.(DataFlow::CfgNode).getNode().(NameNode).getId() in [
|
||||
"TAINTED_STRING", "TAINTED_BYTES", "TAINTED_LIST", "TAINTED_DICT"
|
||||
]
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
|
||||
Reference in New Issue
Block a user