WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
149376
[Web IDL] Add support for [PutForwards=XXX] IDL extended attribute
https://bugs.webkit.org/show_bug.cgi?id=149376
Summary
[Web IDL] Add support for [PutForwards=XXX] IDL extended attribute
Chris Dumez
Reported
2015-09-19 16:23:50 PDT
[Web IDL] Add support for [PutForwards=XXX] IDL extended attribute:
https://heycam.github.io/webidl/#PutForwards
As an initial proof of concept, use it for Document.location as per the specification instead of using custom bindings:
https://html.spec.whatwg.org/multipage/dom.html#the-document-object
More attributes can be ported later.
Attachments
Patch
(27.05 KB, patch)
2015-09-19 16:53 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(27.46 KB, patch)
2015-09-19 18:11 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Show Obsolete
(1)
View All
Add attachment
proposed patch, testcase, etc.
Chris Dumez
Comment 1
2015-09-19 16:53:06 PDT
Created
attachment 261590
[details]
Patch
Darin Adler
Comment 2
2015-09-19 17:10:58 PDT
Comment on
attachment 261590
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261590&action=review
Looks OK, but there is one significant problem.
> Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp:3098 > + auto* forwardedImpl = WTF::getPtr(castedThis->impl().putForwardsAttribute()); > + if (!forwardedImpl) > + return; > + auto& impl = *forwardedImpl; > + String nativeValue = value.toString(exec)->value(exec); > + if (UNLIKELY(exec->hadException())) > + return; > + impl.setName(nativeValue);
We can see here that we have a possible object lifetime problem. The reason the code uses WTF::getPtr is that the attribute might return a RefPtr, for example. The whole reason a function would return a RefPtr is that it might want to return a new object where the only owner is the RefPtr. So once we put the pointer into a raw pointer and then let the expression fall out of scope, we have a pointer to a deleted object. This is not a problem when we use the result of getPtr to call a function, because the underlying RefPtr doesn’t get deallocated until the end of the full expression. I think the best thing to do for this would be to leave out the call to WTF::getPtr; then this won’t compile if the underlying function returns a RefPtr.
Darin Adler
Comment 3
2015-09-19 17:12:27 PDT
Comment on
attachment 261590
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261590&action=review
>> Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp:3098 >> + impl.setName(nativeValue); > > We can see here that we have a possible object lifetime problem. The reason the code uses WTF::getPtr is that the attribute might return a RefPtr, for example. The whole reason a function would return a RefPtr is that it might want to return a new object where the only owner is the RefPtr. So once we put the pointer into a raw pointer and then let the expression fall out of scope, we have a pointer to a deleted object. > > This is not a problem when we use the result of getPtr to call a function, because the underlying RefPtr doesn’t get deallocated until the end of the full expression. > > I think the best thing to do for this would be to leave out the call to WTF::getPtr; then this won’t compile if the underlying function returns a RefPtr.
Another option would be to generate this code: auto a = castedThis->impl().putForwardsAttribute(); auto* b = WTF::getPtr(a); if (!b) return; auto& impl = *b; Not sure what "a" and "b" should be named, though.
Chris Dumez
Comment 4
2015-09-19 17:19:03 PDT
Comment on
attachment 261590
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261590&action=review
>>> Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp:3098 >>> + impl.setName(nativeValue); >> >> We can see here that we have a possible object lifetime problem. The reason the code uses WTF::getPtr is that the attribute might return a RefPtr, for example. The whole reason a function would return a RefPtr is that it might want to return a new object where the only owner is the RefPtr. So once we put the pointer into a raw pointer and then let the expression fall out of scope, we have a pointer to a deleted object. >> >> This is not a problem when we use the result of getPtr to call a function, because the underlying RefPtr doesn’t get deallocated until the end of the full expression. >> >> I think the best thing to do for this would be to leave out the call to WTF::getPtr; then this won’t compile if the underlying function returns a RefPtr. > > Another option would be to generate this code: > > auto a = castedThis->impl().putForwardsAttribute(); > auto* b = WTF::getPtr(a); > if (!b) > return; > auto& impl = *b; > > Not sure what "a" and "b" should be named, though.
Good point, although it would be weird to call a setter on an object that is temporary. It was assumed that the implementation would retain the forwarded attribute's object. I will revisit before landing.
Darin Adler
Comment 5
2015-09-19 17:25:29 PDT
Comment on
attachment 261590
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261590&action=review
>>>> Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp:3098 >>>> + impl.setName(nativeValue); >>> >>> We can see here that we have a possible object lifetime problem. The reason the code uses WTF::getPtr is that the attribute might return a RefPtr, for example. The whole reason a function would return a RefPtr is that it might want to return a new object where the only owner is the RefPtr. So once we put the pointer into a raw pointer and then let the expression fall out of scope, we have a pointer to a deleted object. >>> >>> This is not a problem when we use the result of getPtr to call a function, because the underlying RefPtr doesn’t get deallocated until the end of the full expression. >>> >>> I think the best thing to do for this would be to leave out the call to WTF::getPtr; then this won’t compile if the underlying function returns a RefPtr. >> >> Another option would be to generate this code: >> >> auto a = castedThis->impl().putForwardsAttribute(); >> auto* b = WTF::getPtr(a); >> if (!b) >> return; >> auto& impl = *b; >> >> Not sure what "a" and "b" should be named, though. > > Good point, although it would be weird to call a setter on an object that is temporary. It was assumed that the implementation would retain the forwarded attribute's object. I will revisit before landing.
I think that’s why it’s good to use a raw pointer and remove the call to getPtr. It makes sense for all the cases where forwarding makes sense. There’s no reason for the attribute value to return a RefPtr; it should just be a raw pointer. And I think location() does return a raw pointer. Maybe might be nice to support a reference too, but not RefPtr or Ref.
Chris Dumez
Comment 6
2015-09-19 17:28:44 PDT
(In reply to
comment #5
)
> Comment on
attachment 261590
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=261590&action=review
> > >>>> Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp:3098 > >>>> + impl.setName(nativeValue); > >>> > >>> We can see here that we have a possible object lifetime problem. The reason the code uses WTF::getPtr is that the attribute might return a RefPtr, for example. The whole reason a function would return a RefPtr is that it might want to return a new object where the only owner is the RefPtr. So once we put the pointer into a raw pointer and then let the expression fall out of scope, we have a pointer to a deleted object. > >>> > >>> This is not a problem when we use the result of getPtr to call a function, because the underlying RefPtr doesn’t get deallocated until the end of the full expression. > >>> > >>> I think the best thing to do for this would be to leave out the call to WTF::getPtr; then this won’t compile if the underlying function returns a RefPtr. > >> > >> Another option would be to generate this code: > >> > >> auto a = castedThis->impl().putForwardsAttribute(); > >> auto* b = WTF::getPtr(a); > >> if (!b) > >> return; > >> auto& impl = *b; > >> > >> Not sure what "a" and "b" should be named, though. > > > > Good point, although it would be weird to call a setter on an object that is temporary. It was assumed that the implementation would retain the forwarded attribute's object. I will revisit before landing. > > I think that’s why it’s good to use a raw pointer and remove the call to > getPtr. It makes sense for all the cases where forwarding makes sense. > There’s no reason for the attribute value to return a RefPtr; it should just > be a raw pointer. And I think location() does return a raw pointer. Maybe > might be nice to support a reference too, but not RefPtr or Ref.
Well, WTF::getPtr() was also useful if the implementation returned a C++ reference, which it can (and should if the pointer cannot be null).
Chris Dumez
Comment 7
2015-09-19 18:11:05 PDT
Created
attachment 261595
[details]
Patch
Chris Dumez
Comment 8
2015-09-19 18:12:17 PDT
Comment on
attachment 261590
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261590&action=review
>>>>>> Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp:3098 >>>>>> + impl.setName(nativeValue); >>>>> >>>>> We can see here that we have a possible object lifetime problem. The reason the code uses WTF::getPtr is that the attribute might return a RefPtr, for example. The whole reason a function would return a RefPtr is that it might want to return a new object where the only owner is the RefPtr. So once we put the pointer into a raw pointer and then let the expression fall out of scope, we have a pointer to a deleted object. >>>>> >>>>> This is not a problem when we use the result of getPtr to call a function, because the underlying RefPtr doesn’t get deallocated until the end of the full expression. >>>>> >>>>> I think the best thing to do for this would be to leave out the call to WTF::getPtr; then this won’t compile if the underlying function returns a RefPtr. >>>> >>>> Another option would be to generate this code: >>>> >>>> auto a = castedThis->impl().putForwardsAttribute(); >>>> auto* b = WTF::getPtr(a); >>>> if (!b) >>>> return; >>>> auto& impl = *b; >>>> >>>> Not sure what "a" and "b" should be named, though. >>> >>> Good point, although it would be weird to call a setter on an object that is temporary. It was assumed that the implementation would retain the forwarded attribute's object. I will revisit before landing. >> >> I think that’s why it’s good to use a raw pointer and remove the call to getPtr. It makes sense for all the cases where forwarding makes sense. There’s no reason for the attribute value to return a RefPtr; it should just be a raw pointer. And I think location() does return a raw pointer. Maybe might be nice to support a reference too, but not RefPtr or Ref. > > Well, WTF::getPtr() was also useful if the implementation returned a C++ reference, which it can (and should if the pointer cannot be null).
I dropped the call to WTF::getPtr() for now. We'll see about supporting implementation methods returning C++ references if it turns out it is needed by any of the PutForwards attributes.
WebKit Commit Bot
Comment 9
2015-09-19 18:59:54 PDT
Comment on
attachment 261595
[details]
Patch Clearing flags on attachment: 261595 Committed
r190023
: <
http://trac.webkit.org/changeset/190023
>
WebKit Commit Bot
Comment 10
2015-09-19 18:59:59 PDT
All reviewed patches have been landed. Closing bug.
Alexey Proskuryakov
Comment 11
2015-09-20 14:38:26 PDT
This introduced a use-after-free detected by ASan and GuardMalloc. Will roll out, as memory corruption on regression tests is especially not OK. Will e-mail an ASan violation log to Chris.
Alexey Proskuryakov
Comment 12
2015-09-20 14:41:54 PDT
Chris will roll out himself if this is not an easy fix.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug