Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
queries/Security/CWE-020/IncompleteHostnameRegex.ql
query: queries/Security/CWE-020/IncompleteHostnameRegex.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
queries/Security/CWE-020/MissingRegexAnchor.ql
query: queries/Security/CWE-020/MissingRegexAnchor.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
Original file line number Diff line number Diff line change
Expand Up @@ -47,63 +47,63 @@ class NSString : NSObject {

func tests(input: String) throws {
_ = try Regex("^a|").firstMatch(in: input)
_ = try Regex("^a|b").firstMatch(in: input) // BAD (missing anchor)
_ = try Regex("^a|b").firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex("a|^b").firstMatch(in: input)
_ = try Regex("^a|^b").firstMatch(in: input)
_ = try Regex("^a|b|c").firstMatch(in: input) // BAD (missing anchor)
_ = try Regex("^a|b|c").firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex("a|^b|c").firstMatch(in: input)
_ = try Regex("a|b|^c").firstMatch(in: input)
_ = try Regex("^a|^b|c").firstMatch(in: input)

_ = try Regex("(^a)|b").firstMatch(in: input)
_ = try Regex("^a|(b)").firstMatch(in: input) // BAD (missing anchor)
_ = try Regex("^a|(b)").firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex("^a|(^b)").firstMatch(in: input)
_ = try Regex("^(a)|(b)").firstMatch(in: input) // BAD (missing anchor)
_ = try Regex("^(a)|(b)").firstMatch(in: input) // $ Alert // BAD (missing anchor)

_ = try Regex("a|b$").firstMatch(in: input) // BAD (missing anchor)
_ = try Regex("a|b$").firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex("a$|b").firstMatch(in: input)
_ = try Regex("a$|b$").firstMatch(in: input)
_ = try Regex("a|b|c$").firstMatch(in: input) // BAD (missing anchor)
_ = try Regex("a|b|c$").firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex("a|b$|c").firstMatch(in: input)
_ = try Regex("a$|b|c").firstMatch(in: input)
_ = try Regex("a|b$|c$").firstMatch(in: input)

_ = try Regex("a|(b$)").firstMatch(in: input)
_ = try Regex("(a)|b$").firstMatch(in: input) // BAD (missing anchor)
_ = try Regex("(a)|b$").firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex("(a$)|b$").firstMatch(in: input)
_ = try Regex("(a)|(b)$").firstMatch(in: input) // BAD (missing anchor)
_ = try Regex("(a)|(b)$").firstMatch(in: input) // $ Alert // BAD (missing anchor)

_ = try Regex(#"^good.com|better.com"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^good\.com|better\.com"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^good\\.com|better\\.com"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^good\\\.com|better\\\.com"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^good\\\\.com|better\\\\.com"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^good.com|better.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^good\.com|better\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^good\\.com|better\\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^good\\\.com|better\\\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^good\\\\.com|better\\\\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)

_ = try Regex("^foo|bar|baz$").firstMatch(in: input) // BAD (missing anchor)
_ = try Regex("^foo|bar|baz$").firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex("^foo|%").firstMatch(in: input)
}

func realWorld(input: String) throws {
// real-world examples that have been anonymized a bit
// the following are bad:
_ = try Regex(#"(\.xxx)|(\.yyy)|(\.zzz)$"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"(^left|right|center)\sbottom$"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"\.xxx|\.yyy|\.zzz$"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"\.xxx|\.yyy|\.zzz$"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"\.xxx|\.yyy|zzz$"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^([A-Z]|xxx[XY]$)"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^(xxx yyy zzz)|(xxx yyy)"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^(xxx yyy zzz)|(xxx yyy)|(1st( xxx)? yyy)|xxx|1st"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^(xxx:)|(yyy:)|(zzz:)"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^(xxx?:)|(yyy:zzz\/)"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^@media|@page"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^\s*(xxx?|yyy|zzz):|xxx:yyy"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^click|mouse|touch"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^http://good\.com|http://better\.com"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^https?://good\.com|https?://better\.com"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^mouse|touch|click|contextmenu|drop|dragover|dragend"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"^xxx:|yyy:"#).ignoresCase().firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"_xxx|_yyy|_zzz$"#).firstMatch(in: input) // BAD (missing anchor)
_ = try Regex(#"(\.xxx)|(\.yyy)|(\.zzz)$"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"(^left|right|center)\sbottom$"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"\.xxx|\.yyy|\.zzz$"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"\.xxx|\.yyy|\.zzz$"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"\.xxx|\.yyy|zzz$"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^([A-Z]|xxx[XY]$)"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^(xxx yyy zzz)|(xxx yyy)"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^(xxx yyy zzz)|(xxx yyy)|(1st( xxx)? yyy)|xxx|1st"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^(xxx:)|(yyy:)|(zzz:)"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^(xxx?:)|(yyy:zzz\/)"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^@media|@page"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^\s*(xxx?|yyy|zzz):|xxx:yyy"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^click|mouse|touch"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^http://good\.com|http://better\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^https?://good\.com|https?://better\.com"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^mouse|touch|click|contextmenu|drop|dragover|dragend"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^xxx:|yyy:"#).ignoresCase().firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"_xxx|_yyy|_zzz$"#).firstMatch(in: input) // $ Alert // BAD (missing anchor)
_ = try Regex(#"em|%$"#).firstMatch(in: input) // BAD (missing anchor) [NOT DETECTED] - not flagged at the moment due to the anchor not being for letters

// the following are MAYBE OK due to apparent complexity; not flagged
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,36 +59,36 @@ func tests(url: String, secure: Bool) throws {
let input = "http://evil.com/?http://good.com"
let inputRange = NSMakeRange(0, input.utf16.count)

_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // BAD (missing anchor)
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // BAD (missing anchor)
_ = try NSRegularExpression(pattern: "^https?://good.com").matches(in: input, range: inputRange) // BAD (missing post-anchor)
_ = try NSRegularExpression(pattern: "(^https?://good1.com)|(^https?://good2.com)").matches(in: input, range: inputRange) // BAD (missing post-anchor)
_ = try NSRegularExpression(pattern: "(https?://good.com)|(^https?://goodie.com)").matches(in: input, range: inputRange) // BAD (missing anchor)
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
_ = try NSRegularExpression(pattern: "^https?://good.com").matches(in: input, range: inputRange) // $ Alert // BAD (missing post-anchor)
_ = try NSRegularExpression(pattern: "(^https?://good1.com)|(^https?://good2.com)").matches(in: input, range: inputRange) // $ Alert // BAD (missing post-anchor)
_ = try NSRegularExpression(pattern: "(https?://good.com)|(^https?://goodie.com)").matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)

_ = try NSRegularExpression(pattern: #"https?:\/\/good.com"#).matches(in: input, range: inputRange) // BAD (missing anchor)
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // BAD (missing anchor)
_ = try NSRegularExpression(pattern: #"https?:\/\/good.com"#).matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
_ = try NSRegularExpression(pattern: "https?://good.com").matches(in: input, range: inputRange) // $ Alert // BAD (missing anchor)

if let _ = try NSRegularExpression(pattern: "https?://good.com").firstMatch(in: input, range: inputRange) { } // BAD (missing anchor)
if let _ = try NSRegularExpression(pattern: "https?://good.com").firstMatch(in: input, range: inputRange) { } // $ Alert // BAD (missing anchor)

let input2 = "something"
let input2Range = NSMakeRange(0, input2.utf16.count)
_ = try NSRegularExpression(pattern: "other").firstMatch(in: input2, range: input2Range) // OK
_ = try NSRegularExpression(pattern: "x.commissary").firstMatch(in: input2, range: input2Range) // OK

_ = try NSRegularExpression(pattern: #"https?://good.com"#).firstMatch(in: input, range: inputRange) // BAD (missing anchor)
_ = try NSRegularExpression(pattern: #"https?://good.com:8080"#).firstMatch(in: input, range: inputRange) // BAD (missing anchor)
_ = try NSRegularExpression(pattern: #"https?://good.com"#).firstMatch(in: input, range: inputRange) // $ Alert // BAD (missing anchor)
_ = try NSRegularExpression(pattern: #"https?://good.com:8080"#).firstMatch(in: input, range: inputRange) // $ Alert // BAD (missing anchor)

let trustedUrlRegexs = [
"https?://good.com", // BAD (missing anchor), referenced below
#"https?:\/\/good.com"#, // BAD (missing anchor), referenced below
"^https?://good.com" // BAD (missing post-anchor), referenced below
"https?://good.com", // $ Alert // BAD (missing anchor), referenced below
#"https?:\/\/good.com"#, // $ Alert // BAD (missing anchor), referenced below
"^https?://good.com" // $ Alert // BAD (missing post-anchor), referenced below
]
for trustedUrlRegex in trustedUrlRegexs {
if let _ = try NSRegularExpression(pattern: trustedUrlRegex).firstMatch(in: input, range: inputRange) { }
}

let trustedUrlRegexs2 = [
"https?://good.com", // BAD (missing anchor), referenced below
"https?://good.com", // $ Alert // BAD (missing anchor), referenced below
]
if let _ = try NSRegularExpression(pattern: trustedUrlRegexs2[0]).firstMatch(in: input, range: inputRange) { }

Expand All @@ -98,13 +98,13 @@ func tests(url: String, secure: Bool) throws {
for _ in notUsedUrlRegexs {
}

_ = try NSRegularExpression(pattern: #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange) // BAD (missing anchor)
_ = try NSRegularExpression(pattern: #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange) // $ Alert // BAD (missing anchor)
_ = try NSRegularExpression(pattern: "https://verygood.com/?id=" + #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange)[0] // OK
_ = try NSRegularExpression(pattern: "http" + (secure ? "s" : "") + "://" + "verygood.com/?id=" + #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange)[0] // OK
_ = try NSRegularExpression(pattern: "verygood.com/?id=" + #"https?:\/\/good.com\/([0-9]+)"#).matches(in: url, range: urlRange)[0] // OK

_ = try NSRegularExpression(pattern: #"\.com|\.org"#).matches(in: input, range: inputRange) // OK, has no domain name
_ = try NSRegularExpression(pattern: #"example\.com|whatever"#).matches(in: input, range: inputRange) // OK, the other disjunction doesn't match a hostname [FALSE POSITIVE]
_ = try NSRegularExpression(pattern: #"example\.com|whatever"#).matches(in: input, range: inputRange) // $ Alert // OK, the other disjunction doesn't match a hostname [FALSE POSITIVE]

// tests for the `isLineAnchoredHostnameRegExp` case

Expand Down
44 changes: 22 additions & 22 deletions swift/ql/test/query-tests/Security/CWE-020/test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,49 +53,49 @@ func testHostnames(myUrl: URL) throws {

_ = try Regex(#"^http://example\.com/"#).firstMatch(in: tainted) // GOOD
_ = try Regex(#"^http://example.com/"#).firstMatch(in: tainted) // GOOD (only '.' here gives a valid top-level domain)
_ = try Regex(#"^http://example.com"#).firstMatch(in: tainted) // BAD (missing anchor)
_ = try Regex(#"^http://example.com"#).firstMatch(in: tainted) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^http://test\.example\.com/"#).firstMatch(in: tainted) // GOOD
_ = try Regex(#"^http://test\.example.com/"#).firstMatch(in: tainted) // GOOD (only '.' here gives a valid top-level domain)
_ = try Regex(#"^http://test\.example.com"#).firstMatch(in: tainted) // BAD (missing anchor)
_ = try Regex(#"^http://test.example.com/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^http://test\.example.com"#).firstMatch(in: tainted) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^http://test.example.com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^http://test[.]example[.]com/"#).firstMatch(in: tainted) // GOOD (alternative method of escaping)

_ = try Regex(#"^http://test.example.net/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^http://test.(example-a|example-b).com/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^http://(.+).example.com/"#).firstMatch(in: tainted) // BAD (incomplete hostname x 2)
_ = try Regex(#"^http://test.example.net/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^http://test.(example-a|example-b).com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^http://(.+).example.com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname x 2)
_ = try Regex(#"^http://(\.+)\.example.com/"#).firstMatch(in: tainted) // GOOD
_ = try Regex(#"^http://(?:.+)\.test\.example.com/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^http://test.example.com/(?:.*)"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^(.+\.(?:example-a|example-b)\.com)/"#).firstMatch(in: tainted) // BAD (missing anchor)
_ = try Regex(#"^(https?:)?//((service|www).)?example.com(?=$|/)"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^(http|https)://www.example.com/p/f/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^(http://sub.example.com/)"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^https?://api.example.com/"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^http://(?:.+)\.test\.example.com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^http://test.example.com/(?:.*)"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^(.+\.(?:example-a|example-b)\.com)/"#).firstMatch(in: tainted) // $ Alert // BAD (missing anchor)
_ = try Regex(#"^(https?:)?//((service|www).)?example.com(?=$|/)"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^(http|https)://www.example.com/p/f/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^(http://sub.example.com/)"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^https?://api.example.com/"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^http[s]?://?sub1\.sub2\.example\.com/f/(.+)"#).firstMatch(in: tainted) // GOOD (it has a capture group after the TLD, so should be ignored)
_ = try Regex(#"^https://[a-z]*.example.com$"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"^(example.dev|example.com)"#).firstMatch(in: tainted) // GOOD (any extended hostname wouldn't be included in the capture group) [FALSE POSITIVE]
_ = try Regex(#"^protos?://(localhost|.+.example.net|.+.example-a.com|.+.example-b.com|.+.example.internal)"#).firstMatch(in: tainted) // BAD (incomplete hostname x3, missing anchor x 1)
_ = try Regex(#"^https://[a-z]*.example.com$"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"^(example.dev|example.com)"#).firstMatch(in: tainted) // $ Alert // GOOD (any extended hostname wouldn't be included in the capture group) [FALSE POSITIVE]
_ = try Regex(#"^protos?://(localhost|.+.example.net|.+.example-a.com|.+.example-b.com|.+.example.internal)"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname x3, missing anchor x 1)

_ = try Regex(#"^http://(..|...)\.example\.com/index\.html"#).firstMatch(in: tainted) // GOOD (wildcards are intentional)
_ = try Regex(#"^http://.\.example\.com/index\.html"#).firstMatch(in: tainted) // GOOD (the wildcard is intentional)
_ = try Regex(#"^(foo.example\.com|whatever)$"#).firstMatch(in: tainted) // DUBIOUS (one disjunction doesn't even look like a hostname) [DETECTED incomplete hostname, missing anchor]
_ = try Regex(#"^(foo.example\.com|whatever)$"#).firstMatch(in: tainted) // $ Alert // DUBIOUS (one disjunction doesn't even look like a hostname) [DETECTED incomplete hostname, missing anchor]

_ = try Regex(#"^test.example.com$"#).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(#"test.example.com"#).wholeMatch(in: tainted) // BAD (incomplete hostname, missing anchor)
_ = try Regex(#"^test.example.com$"#).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)
_ = try Regex(#"test.example.com"#).wholeMatch(in: tainted) // $ Alert // BAD (incomplete hostname, missing anchor)

_ = try Regex(id(id(id(#"test.example.com$"#)))).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try Regex(id(id(id(#"test.example.com$"#)))).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)

let hostname = #"test.example.com$"# // BAD (incomplete hostname) [NOT DETECTED]
_ = try Regex("\(hostname)").firstMatch(in: tainted)

var domain = MyDomain("")
domain.hostname = #"test.example.com$"# // BAD (incomplete hostname)
domain.hostname = #"test.example.com$"# // $ Alert // BAD (incomplete hostname)
_ = try Regex(domain.hostname).firstMatch(in: tainted)

func convert1(_ domain: MyDomain) throws -> Regex<AnyRegexOutput> {
return try Regex(domain.hostname)
}
_ = try convert1(MyDomain(#"test.example.com$"#)).firstMatch(in: tainted) // BAD (incomplete hostname)
_ = try convert1(MyDomain(#"test.example.com$"#)).firstMatch(in: tainted) // $ Alert // BAD (incomplete hostname)

let domains = [ MyDomain(#"test.example.com$"#) ] // BAD (incomplete hostname) [NOT DETECTED]
func convert2(_ domain: MyDomain) throws -> Regex<AnyRegexOutput> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
experimental/Security/CWE-022/UnsafeUnpack.ql
query: experimental/Security/CWE-022/UnsafeUnpack.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
Loading