-
-
Notifications
You must be signed in to change notification settings - Fork 32
Harden model download integrity (pre-release audit, wave 2) #536
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -59,6 +59,29 @@ final class ModelFileValidatorTests: XCTestCase { | |||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // MARK: - validateCompleteness | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| func test_validateCompleteness_passesWhenSizeMatchesDeclaredLength() throws { | ||||||||||||||||||||||||||
| let url = try makeFixture(contents: Data(repeating: 0xAB, count: 100)) | ||||||||||||||||||||||||||
| XCTAssertNoThrow(try ModelFileValidator.validateCompleteness(of: url, declaredContentLength: 100)) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| func test_validateCompleteness_throwsOnTruncatedBody() throws { | ||||||||||||||||||||||||||
| let url = try makeFixture(contents: Data(repeating: 0xAB, count: 60)) | ||||||||||||||||||||||||||
| XCTAssertThrowsError(try ModelFileValidator.validateCompleteness(of: url, declaredContentLength: 100)) { error in | ||||||||||||||||||||||||||
| guard case ModelFileValidator.ValidationError.sizeMismatch = error else { | ||||||||||||||||||||||||||
| XCTFail("Expected sizeMismatch, got \(error)") | ||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| func test_validateCompleteness_noOpsWhenLengthUnknown() throws { | ||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||||||||||||||||||||||||||
| let url = try makeFixture(contents: Data(repeating: 0xAB, count: 60)) | ||||||||||||||||||||||||||
| XCTAssertNoThrow(try ModelFileValidator.validateCompleteness(of: url, declaredContentLength: -1)) | ||||||||||||||||||||||||||
| XCTAssertNoThrow(try ModelFileValidator.validateCompleteness(of: url, declaredContentLength: 0)) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // MARK: - validateSHA256 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| func test_validateSHA256_passesForKnownChecksum() throws { | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
promoteStagedFile:fileExistsis checked, thenmoveItemis called in theelsebranch. If another process or a concurrent download creates the destination between those two calls,moveItemthrows "file already exists," the staging file is cleaned up, and the download is surfaced as failed — even though the data is fully valid.FileManager.replaceItemAthandles both the "destination exists" and "destination absent" cases atomically, so thefileExistsbranch is unnecessary.