Changeset 270559 in webkit
- Timestamp:
- Dec 8, 2020 3:45:23 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r270557 r270559 1 2020-12-08 Chris Dumez <cdumez@apple.com> 2 3 Potential crash under [WKRemoteObjectEncoder encodeObject:forKey:] when the object graph contains a cycle 4 https://bugs.webkit.org/show_bug.cgi?id=219620 5 <rdar://71551776> 6 7 Reviewed by Geoffrey Garen. 8 9 Update WKRemoteObjectEncoder to detect cycles when encoding objects. When a cycle is detected, we 10 first attempt to encode a default-initialized object of the same type instead. If that fails, we 11 raise a NSInvalidArgumentException. 12 13 Based on crashes in the wild, we have evidence that such cycles are occuring and I suspect this is 14 caused by Norton Safe Web extension somehow. 15 16 * Shared/API/Cocoa/WKRemoteObjectCoder.mm: 17 (-[WKRemoteObjectEncoder init]): 18 (encodeObject): 19 1 20 2020-12-08 Simon Fraser <simon.fraser@apple.com> 2 21 -
trunk/Source/WebKit/Shared/API/Cocoa/WKRemoteObjectCoder.mm
r263016 r270559 32 32 #import "APINumber.h" 33 33 #import "APIString.h" 34 #import "Logging.h" 34 35 #import "NSInvocationSPI.h" 35 36 #import "_WKRemoteObjectInterfaceInternal.h" 36 37 #import <objc/runtime.h> 37 38 #import <wtf/RetainPtr.h> 39 #import <wtf/Scope.h> 38 40 #import <wtf/SetForScope.h> 39 41 #import <wtf/text/CString.h> … … 62 64 63 65 API::Dictionary* _currentDictionary; 66 RetainPtr<NSMutableSet> _objectsBeingEncoded; // Used to detect cycles. 64 67 } 65 68 … … 71 74 _rootDictionary = API::Dictionary::create(); 72 75 _currentDictionary = _rootDictionary.get(); 76 _objectsBeingEncoded = adoptNS([[NSMutableSet alloc] init]); 73 77 74 78 return self; … … 305 309 if (!objectClass) 306 310 [NSException raise:NSInvalidArgumentException format:@"-classForCoder returned nil for %@", object]; 311 312 if ([encoder->_objectsBeingEncoded containsObject:object]) { 313 RELEASE_LOG_FAULT(IPC, "WKRemoteObjectCode::encodeObject: Object of type '%{private}s' contains a cycle", class_getName(object_getClass(object))); 314 @try { 315 // Try to encode a newly initialized object instead. 316 id newObject = [[[[object class] alloc] init] autorelease]; 317 object = newObject; 318 } @catch (NSException *e) { 319 [NSException raise:NSInvalidArgumentException format:@"Object of type '%s' contains a cycle", class_getName(object_getClass(object))]; 320 } 321 } 322 323 [encoder->_objectsBeingEncoded addObject:object]; 324 auto exitScope = makeScopeExit([encoder, object] { 325 [encoder->_objectsBeingEncoded removeObject:object]; 326 }); 307 327 308 328 encoder->_currentDictionary->set(classNameKey, API::String::create(class_getName(objectClass))); -
trunk/Tools/ChangeLog
r270558 r270559 1 2020-12-08 Chris Dumez <cdumez@apple.com> 2 3 Potential crash under [WKRemoteObjectEncoder encodeObject:forKey:] when the object graph contains a cycle 4 https://bugs.webkit.org/show_bug.cgi?id=219620 5 6 Reviewed by Geoffrey Garen. 7 8 Add API test coverage. 9 10 * TestWebKitAPI/Tests/WebKitCocoa/RemoteObjectRegistry.h: 11 * TestWebKitAPI/Tests/WebKitCocoa/RemoteObjectRegistry.mm: 12 (TEST): 13 * TestWebKitAPI/Tests/WebKitCocoa/RemoteObjectRegistryPlugIn.mm: 14 (-[RemoteObjectRegistryPlugIn takeDictionary:completionHandler:]): 15 1 16 2020-12-08 Jonathan Bedard <jbedard@apple.com> 2 17 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RemoteObjectRegistry.h
r258095 r270559 49 49 - (void)takeUnsignedLong:(unsigned long)value completionHandler:(void (^)(unsigned long value))completionHandler; 50 50 - (void)takeLong:(long)value completionHandler:(void (^)(long value))completionHandler; 51 - (void)takeDictionary:(NSDictionary *)value completionHandler:(void (^)(NSDictionary *value))completionHandler; 51 52 - (void)doNotCallCompletionHandler:(void (^)())completionHandler; 52 53 - (void)sendRequest:(NSURLRequest *)request response:(NSURLResponse *)response challenge:(NSURLAuthenticationChallenge *)challenge error:(NSError *)error completionHandler:(void (^)(NSURLRequest *, NSURLResponse *, NSURLAuthenticationChallenge *, NSError *))completionHandler; -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RemoteObjectRegistry.mm
r258095 r270559 127 127 isDone = false; 128 128 129 class DoneWhenDestroyed : public RefCounted<DoneWhenDestroyed> {130 public:131 DoneWhenDestroyed(bool& isDone)132 : isDone(isDone) { }133 ~DoneWhenDestroyed() { isDone = true; }134 private:135 bool& isDone;136 };137 138 {139 RefPtr<DoneWhenDestroyed> doneWhenDestroyed = adoptRef(*new DoneWhenDestroyed(isDone));140 [object doNotCallCompletionHandler:[doneWhenDestroyed]() {141 }];142 }143 144 TestWebKitAPI::Util::run(&isDone);145 146 129 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://webkit.org/"]]; 147 130 NSHTTPURLResponse *response = [[[NSHTTPURLResponse alloc] initWithURL:[NSURL URLWithString:@"https://webkit.org/"] statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:@{ @"testFieldName" : @"testFieldValue" }] autorelease]; … … 159 142 }]; 160 143 TestWebKitAPI::Util::run(&isDone); 144 145 isDone = false; 146 147 bool exceptionThrown = false; 148 NSMutableDictionary *child = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"foo", @"name", [NSNumber numberWithInt:1], @"value", nil]; 149 NSMutableDictionary *dictionaryWithCycle = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"root", @"name", child, @"child", nil]; 150 [child setValue:dictionaryWithCycle forKey:@"parent"]; // Creates a cycle. 151 @try { 152 [object takeDictionary:dictionaryWithCycle completionHandler:^(NSDictionary* value) { 153 NSString *name = [value objectForKey:@"name"]; 154 EXPECT_WK_STREQ(@"root", name); 155 NSDictionary *child = [value objectForKey:@"child"]; 156 EXPECT_TRUE(!!child); 157 NSString* childName = [child objectForKey:@"name"]; 158 EXPECT_WK_STREQ(@"foo", childName); 159 NSNumber *childValue = [child objectForKey:@"value"]; 160 EXPECT_EQ(1, [childValue integerValue]); 161 // We should have encoded parent as an empty NSDictionary. 162 NSDictionary *childParent = [child objectForKey:@"parent"]; 163 EXPECT_TRUE(!!childParent); 164 EXPECT_EQ(0U, [childParent count]); 165 isDone = true; 166 }]; 167 TestWebKitAPI::Util::run(&isDone); 168 isDone = false; 169 } @catch (NSException *e) { 170 exceptionThrown = true; 171 } 172 EXPECT_FALSE(exceptionThrown); 173 174 class DoneWhenDestroyed : public RefCounted<DoneWhenDestroyed> { 175 public: 176 DoneWhenDestroyed(bool& isDone) 177 : isDone(isDone) { } 178 ~DoneWhenDestroyed() { isDone = true; } 179 private: 180 bool& isDone; 181 }; 182 183 { 184 RefPtr<DoneWhenDestroyed> doneWhenDestroyed = adoptRef(*new DoneWhenDestroyed(isDone)); 185 [object doNotCallCompletionHandler:[doneWhenDestroyed]() { 186 }]; 187 } 188 189 TestWebKitAPI::Util::run(&isDone); 161 190 } 162 191 } -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RemoteObjectRegistryPlugIn.mm
r258095 r270559 105 105 } 106 106 107 - (void)takeDictionary:(NSDictionary *)value completionHandler:(void (^)(NSDictionary *value))completionHandler 108 { 109 completionHandler(value); 110 } 111 107 112 - (void)doNotCallCompletionHandler:(void (^)())completionHandler 108 113 {
Note: See TracChangeset
for help on using the changeset viewer.