Skip to content

Swift: rename ugly names in the Function AST hierarchy#12936

Merged
d10c merged 11 commits into
github:mainfrom
d10c:swift/rename-functions
May 1, 2023
Merged

Swift: rename ugly names in the Function AST hierarchy#12936
d10c merged 11 commits into
github:mainfrom
d10c:swift/rename-functions

Conversation

@d10c
Copy link
Copy Markdown
Contributor

@d10c d10c commented Apr 26, 2023

Rename AST nodes in the Function hierarchy to be more in line with Swift terminology and naming conventions of other QL-supported languages.

The first commit defines the changes, the rest of them are the necessary fixups.

private import codeql.swift.elements
private import codeql.swift.generated.ParentChild

// Internal classes are not imported by the tests:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't manage to amend the ql_test*.mustache templates to output the full import path in case of @ql.internal-marked classes, but that's what should ideally replace this.

Copy link
Copy Markdown
Contributor

@MathiasVP MathiasVP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fantastic! I'll give others some time to 👀 the PR as well, but I'm very happy just merging the PR as-is 😄

Comment thread swift/schema.py

class AbstractFunctionDecl(GenericContext, ValueDecl, Callable):
@group("decl")
class Function(GenericContext, ValueDecl, Callable):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

@geoffw0
Copy link
Copy Markdown
Contributor

geoffw0 commented Apr 26, 2023

First commit LGTM (I've only very briefly reviewed the rest of the changes). 👍

@d10c d10c force-pushed the swift/rename-functions branch from 6667a2b to 91a151e Compare April 26, 2023 13:47
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 26, 2023

QHelp previews:

swift/ql/src/queries/Security/CWE-135/StringLengthConflation.qhelp

String length conflation

Using a length value from an NSString in a String, or a count from a String in an NSString, may cause unexpected behavior including (in some cases) buffer overwrites. This is because certain unicode sequences are represented as one character in a String but as a sequence of multiple characters in an NSString. For example, a 'thumbs up' emoji with a skin tone modifier (👍🏿) is represented as U+1F44D (👍) then the modifier U+1F3FF.

This issue can also arise from using the values of String.utf8.count, String.utf16.count or String.unicodeScalars.count in an unsuitable place.

Recommendation

Use String.count when working with a String. Use NSString.length when working with an NSString. Do not mix values for lengths and offsets between the two types as they are not compatible measures.

If you need to convert between Range and NSRange, do so directly using the appropriate initializer. Do not attempt to use incompatible length and offset values to accomplish conversion.

Example

In the following example, a String is converted to NSString, but a range is created from the String to do some processing on it.


func myFunction(s: String) {
	let ns = NSString(string: s)
	let nsrange = NSMakeRange(0, s.count) // BAD: String length used in NSMakeRange

	// ... use nsrange to process ns
}

This is dangerous because, if the input contains certain characters, the range computed on the String will be wrong for the NSString. This will lead to incorrect behaviour in the string processing that follows. To fix the problem, we can use NSString.length to create the NSRange instead, as follows:


func myFunction(s: String) {
	let ns = NSString(string: s)
	let nsrange = NSMakeRange(0, ns.length) // Fixed: NSString length used in NSMakeRange

	// ... use nsrange to process ns
}

References

swift/ql/src/queries/Security/CWE-943/PredicateInjection.qhelp

Predicate built from user-controlled sources

Predicates represent logical conditions that can be used to check whether an object matches them. If a predicate is built from user-provided data without sufficient sanitization, an attacker may be able to change the overall meaning of the predicate.

Recommendation

When building a predicate from untrusted data, you should either pass it to the appropriate arguments parameter during initialization, or as an array of substitution variables before evaluation. You should not append or concatenate it to the body of the predicate.

Example

In the following insecure example, NSPredicate is built directly from data obtained from an HTTP request. This is untrusted, and can be arbitrarily set by an attacker to alter the meaning of the predicate:

let remoteString = try String(contentsOf: URL(string: "https://example.com/")!)

let filenames: [String] = ["img1.png", "img2.png", "img3.png", "img.txt", "img.csv"]

let predicate = NSPredicate(format: "SELF LIKE \(remoteString)")
let filtered = filenames.filter(){ filename in
    predicate.evaluate(with: filename)
}
print(filtered)

A better way to do this is to use the arguments parameter of NSPredicate's initializer. This prevents attackers from altering the meaning of the predicate, even if they control the externally obtained data, as seen in the following secure example:

let remoteString = try String(contentsOf: URL(string: "https://example.com/")!)

let filenames: [String] = ["img1.png", "img2.png", "img3.png", "img.txt", "img.csv"]

let predicate = NSPredicate(format: "SELF LIKE %@", remoteString)
let filtered = filenames.filter(){ filename in
    predicate.evaluate(with: filename)
}
print(filtered)

References

@d10c d10c changed the title Swift/rename-functions Swift: rename ugly names in the Function AST hierarchy Apr 26, 2023
@d10c d10c marked this pull request as ready for review April 26, 2023 15:04
@d10c d10c requested a review from a team as a code owner April 26, 2023 15:04
Copy link
Copy Markdown
Contributor

@MathiasVP MathiasVP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once DCA is happy!

Copy link
Copy Markdown
Contributor

@geoffw0 geoffw0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for spotting the two places where the .qhelp docs needed updating. This is minor and should not need a docs review.

LGTM. 🎉

@d10c d10c merged commit 383b2e1 into github:main May 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants