-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Fix Core Data crash related to media errors #17759
Conversation
You can trigger an installable build for these changes by visiting CircleCI here. |
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.
The changes look good to me. I'm not sure if there is an easy way to test the sad path nor if it would be useful for these edge cases, but we probably should if it's not a large undertaking?
You can trigger optional UI/connected tests for these changes by visiting CircleCI here. |
68e6289
to
917cadf
Compare
Thanks @ttahmouch! I'm going to take a little more time on this PR because the scope of how this crash can be triggered is potentially larger than just what I've identified here. |
917cadf
to
33eb87c
Compare
@@ -1322,7 +1322,7 @@ - (void)testMigrationFrom103To104CustomTransformers | |||
// Media has an Error transformer | |||
Media *media1 = (Media *)[NSEntityDescription insertNewObjectForEntityForName:[Media entityName] inManagedObjectContext:context]; | |||
media1.blog = blog1; | |||
NSError *error1 = [NSError errorWithDomain:NSURLErrorDomain code:100 userInfo:@{ @"reason": @"test" }]; | |||
NSError *error1 = [NSError errorWithDomain:NSURLErrorDomain code:100 userInfo:@{ NSLocalizedDescriptionKey: @"test" }]; |
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.
👍
if (customErrorMessage) { | ||
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init]; | ||
NSMutableDictionary *userInfo = [error.userInfo mutableCopy]; |
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.
This reverts the fix introduced here in favor of passing all UserInfo
values up to the new setter, which could cherry pick more if needed in the future.
error = [[NSError alloc] initWithDomain:value.domain code:value.code userInfo:userInfo]; | ||
} | ||
|
||
[self willChangeValueForKey:@"error"]; |
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.
The setter boilerplate was generated from Xcode, so it makes me feel better about its legitimacy. 😄
85f783d
to
873aaf8
Compare
@frosty, would you mind giving this PR a look over since you'd worked on the transformers part? I'm totally open to a more optimal solution than the setter method if there are better ideas. 🙇 |
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.
The changes look good to me overall.
I'm just not positive replacing the originally emitted NSError
is the best approach because I don't know if the state that was being encoded and decoded conforming to NSSecureCoding
was needed at all, or if it could have simply been ignored if non-conformant.
Generated by 🚫 dangerJS |
I'm not 100% sure on this myself but it may be a requirement to conform now. #15167 has some information where warnings appeared starting with Xcode 12. |
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.
The code changes look good to me, and I can't think of any other places we use the errors other than those you've identified.
However, when testing I followed the steps on both trunk
and this branch, and I was unable to cause the original crash to happen on trunk
so I can't 100% verify that these changes have made a difference there!
Thanks @frosty! I'll double-check this to make sure nothing has changed since the PR started. |
I just wanted to follow up that I was still able to reproduce the crash in Thanks to both of you for the reviews. 🙇 |
This PR aims to fix a Core Data crash when persisting Media errors due to underlying types in
UserInfo
that don't adoptNSSecureCoding
.The solution proposed here is to strip all but explicitly defined keys in the setter of
Media.error
.Overview example:
An NSError is thrown by iOS that there's no Internet connectivity. Its
UserInfo
dictionary contains anNSUnderlyingError
which contains an object whose class doesn't conform toNSSecureCoding
. It also contains other standard keys such asNSLocalizedDescription
, andNSErrorFailingURLKey
.Before this change:
When saving the context, Core Data would throw an exception once it reached the object that couldn't be encoded, because it didn't adopt
NSSecureCoding
.After this change:
When saving the context, Core Data only encodes
NSLocalizedDescription
with no error. The persisted error is a stripped down encodable version of the original.Related:
To test:
On a self-hosted site not connected to Jetpack:
On a WordPress.com site:
Other context
Exact error that would be produced:
Regression Notes
Because we're only cherrypicking one field from the error now (
NSLocalizedDescription
), there's a possibility other fields were used somewhere else in the app.What I did to test those areas of impact (or what existing automated tests I relied on)
The testing steps above. I relied on the Core Data migration tests from version 103 to 104 of the data model.
What automated tests I added (or what prevented me from doing so)
I updated the Core Data migration tests to test that keys that aren't explicitly defined in the setter of Media.error aren't included.
PR submission checklist:
RELEASE-NOTES.txt
if necessary.