Issue metadata
Sign in to add a comment
|
Heap-use-after-free in blink::LayoutBlockFlow::addOverhangingFloats |
||||||||||||||||||||||||
Issue descriptionDetailed report: https://cluster-fuzz.appspot.com/testcase?key=4730470358319104 Fuzzer: inferno_layout_test_unmodified Job Type: linux_asan_chrome_v8_arm Platform Id: linux Crash Type: Heap-use-after-free READ 4 Crash Address: 0xbb1316d4 Crash State: blink::LayoutBlockFlow::addOverhangingFloats blink::LayoutBlockFlow::layoutBlockChild blink::LayoutBlockFlow::layoutBlockChildren Sanitizer: address (ASAN) Recommended Security Severity: High Regressed: https://cluster-fuzz.appspot.com/revisions?job=linux_asan_chrome_v8_arm&range=449916:449922 Reproducer Testcase: https://cluster-fuzz.appspot.com/download/AMIfv96TzuP1asCA0bQUVHM4SBgNE_bqavCr1k7zvuQLOalpFsjl2tl_GeclssfNXo_sb4o9q9Q2g5d8OSdQzaw_nRLjjqMl7gmK1YRFapvRsrh2Va3Z0KCkC7s_QtdBy0bp1KMUUBO01MfFC7Cl-wfeyoJmkQM5M99-Kww1bg578Aww9rkp_t0EABBwl2MF-T4KjGWWX9Hd7uJOEyTw6Sc0pO0rZ8wXMBscds-YkC37Lad9FXSyutCiLB_N3PxXUxGyTATrYEIYZvsJBB8wSZVx0hKpRNaArJC1OczESn9OP7MRInM8URseiZpclskCgQwZN_dxNkEdkKTNSWSQm_WIg2ysVMHCI6nFHIBfoTPiEuAD72y5UKQ?testcase_id=4730470358319104 Issue filed automatically. See https://dev.chromium.org/Home/chromium-security/bugs/reproducing-clusterfuzz-bugs for more information.
,
Mar 4 2017
Needs bisect, don't think it's from my patch, but none of the other patches look suspect.
,
Mar 4 2017
,
Mar 4 2017
This issue is a security regression. If you are not able to fix this quickly, please revert the change that introduced it. For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
,
Mar 4 2017
,
Mar 6 2017
,
Mar 7 2017
I'm having a quick look at this now. Adding eae since it seems to be in layout.
,
Mar 7 2017
+robhogan, our resident float expert.
,
Mar 7 2017
So I poked around for a while, and all I found was a weird thing, demonstrated in this CL: https://codereview.chromium.org/2733173002 in LayoutBlockFlow::addOverhangingFloats, one of the FloatingObjects in m_floatingObjects contains a hanging pointer to a LayoutObject in its m_layoutObject member. I didn't figure out how that happened by looking at the code, hopefully one of the Layout folks knows!
,
Mar 7 2017
,
Mar 7 2017
The test case is not very reducible, but I'm pretty sure this is because we delete floats from the orthogonal subtree in layoutOrthogonalWritingModeRoots() before laying out the main tree. (Crash goes away if I remove the vertical-mode-lr or remove removeFloatingObjectsForSubtreeRoot()). kojii@ - this looks like one for you I'm afraid! :(
,
Mar 9 2017
We're close to promoting M58 to Beta (next week March 16th). This bug is listed as RB-Beta-blocker. Can you please take a look at this bug and resolve before Beta promotion?
,
Mar 9 2017
Looking. This is reproducible for me as of ToT, and since it has float and writing-mode, layoutOrthogonalWritingModeRoots() is one possible suspect. From the stack trace, the LayoutObject is deleted in surroundContents(). Then within the event handler from surroundContents(), it calls surroundContents(), and do it recursively. Finally when surroundContents() tries to set selection, we read the deleted LayoutObject. Talked with tkent@. The suspected CL in #10 https://codereview.chromium.org/2687273002 changes the selection behavior, so that might have triggered this problem. Also, surroundContents() not suppressing events until its operation is done isn't probably desired, but he suspects this could be reproducible even if surroundContents() suppressed events until its operation is done. I'll look into more on layoutOrthogonalWritingModeRoots() and floats, then consult again with tkent@ if needed.
,
Mar 9 2017
This is probably similar to issue 656419, where too much removeFloatingObjects() may lead to problem. I still don't have good idea why it can be so, instinct tells me opposite, but issue 656419 fixed by reducing removeFloatingObjects(). If I skip removeFloatingObjects() all together, this is gone. Looking for where we rebuild m_floatingObjects and we're probably not applying exactly the same condition, but this doesn't look easy.
,
Mar 9 2017
Or maybe another approach; we disable our optimization to delay removeFloatingObjects() until next layout under certain conditions, maybe when crossing writing-modes boundary? Either way, I will need to understand how we rebuild m_floatingObjects.
,
Mar 9 2017
Need to borrow the bug, to be able to see the fuzzer report.
,
Mar 9 2017
You're more than welcome to take it if you'd like ;-)
,
Mar 9 2017
WIP sent for review https://codereview.chromium.org/2737253003 Some notes on repro. While minimizing JS isn't easy, CSS is easy. We need 4 properties: float:left or right display:table writing-mode:vertical-lr margin-bottom:15in tkent@ and yosin@ helped me to analyze DOM parts. Range.surroundContents(newParent); can be re-written as: while (newParent.firstChild) newParent.removeChild(newParent.lastChild); var fragment = range.extractContents(); range.insertNode(newParent); newParent.appendChild(fragment); document.body.offsetTop; When I replaced Range.surroundContents() with this JS, it crashes in document.body.offsetTop when it calls updateLayout(). So I considered batching events in Range.surroundContents() but the bug should be reproducible by the above JS. CL in #10 https://codereview.chromium.org/2687273002 might have triggered this because it changes the selection code, which may call updateLayout() at the end of Range.surroundContents(). Reverting it might fix this repro, but the root cause is likely to be different. What is happening, as far as I understand at this point, is: 1. A float (probably in a table cell?) has large height (margin-bottom:15in probably makes this) to overhang to next cell or next block after the table, and that its pointer is copied to multiple ancestors by LayoutBlockFlow::addOverhangingFloats(). 2. Create a situation where one of such ancestors has needsLayout() but its descendants that has pointers to the float are layout-clean. 3. Have an orthogonal root that has the ancestor as its containing block, or one of the descendants. 4. A child of an anonymous LayoutBlockFlow keeps the pointer. I'm not sure if this is related. 5. Either 3 (the orthogonal subtree layout) or the table layout algorithm might help to create the situation 2. After the floating object was destroyed, next new LayoutObject is allocated at the same address, both on Win and Linux. This is probably unrelated, but as a record in case.
,
Mar 9 2017
Reduced test case. Haven't tried to debug it yet.
,
Mar 10 2017
Superb, thank you Morten!
,
Mar 10 2017
Here's a smaller test case. It doesn't crash, neither width nor without ASAN. Instead it shows a visual rendering error, and it pertains to the same bug. There are pointers to dead LayoutObjects when this happens. Disabling removeFloatingObjectsForSubtreeRoot() corrects the situation. But I suppose we're not ready for a fix like that.
For testing, I stuck this into FrameView.cpp and called it before and after any layout operation, to look for pointers to dead objects. And it fails with the test case attached.
static void assertAgainstDeath(const LayoutView* view) {
for (const LayoutObject* walker = view; walker;
walker = walker->nextInPreOrder()) {
if (!walker->isLayoutBlockFlow())
continue;
const FloatingObjects* flobs = toLayoutBlockFlow(walker)->floatingObjects();
if (!flobs)
continue;
const FloatingObjectSet& floatingObjectSet = flobs->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end;
++it) {
const FloatingObject& floatingObject = *it->get();
// Looks like our debug allocator sets deleted memory to a
// 0xcdcdcdcdcdcdcdcd pattern, and the following check will fail when used
// on dead objects, at least with the current LayoutObject bitfield
// layout.
DCHECK(floatingObject.layoutObject()->getSelectionState() <= SelectionBoth);
}
}
}
I've added comments in the test case to explain what I think is going on here.
The comment in removeFloatingObjectsForSubtreeRoot() suggests that we deliberately leave pointers to dead LayoutObject objects around for the next layout. This sounds horrible and should be fixed! Then we can just get rid of removeFloatingObjectsForSubtreeRoot().
As long as we allow leaving pointers to dead objects around, however, kojii's fix in https://codereview.chromium.org/2737253003 seems like the right thing to me.
I don't intend to work on an actual fix, so, while kojii's offer in #c17 was very generous, I humbly decline, and assign it back to you, kojii. :)
,
Mar 10 2017
,
Mar 11 2017
ClusterFuzz has detected this issue as fixed in range 455700:456019. Detailed report: https://clusterfuzz.com/testcase?key=4730470358319104 Fuzzer: inferno_layout_test_unmodified Job Type: linux_asan_chrome_v8_arm Platform Id: linux Crash Type: Heap-use-after-free READ 4 Crash Address: 0xbb131a94 Crash State: blink::LayoutBlockFlow::addOverhangingFloats blink::LayoutBlockFlow::layoutBlockChild blink::LayoutBlockFlow::layoutBlockChildren Sanitizer: address (ASAN) Recommended Security Severity: High Regressed: https://clusterfuzz.com/revisions?job=linux_asan_chrome_v8_arm&range=449916:449922 Fixed: https://clusterfuzz.com/revisions?job=linux_asan_chrome_v8_arm&range=455700:456019 Reproducer Testcase: https://clusterfuzz.com/download/AMIfv95KOh7zhnaaon78hz5gINd0iHKtZNEzXgqcc3ePOGSpGzm3LbWs6haG2QBnhQqEw9t6IGnbU6feT7_dAs0Kxu0eWuR7qJ-lzp5MyrHPT27Tn9S8jGirCocVimC-NjSRCxF_BOK-GW0PboMTiVZiYrQcVuBzRp2U4b9uQsA6DczSkYXeNzusvmQpBuHAHO73qL3HUdW4SC163NAaA0SS-QUPc1pzth-LH2FCtwVfnwVhCRhf9UiZtM1KtpJp1gc4AfB4keCXJs_WeSaowiiWTKNW8SNjuMhXDyoBitv4wXu0mQod6wuBLIc0CSuYxbXqtraHKQ-mdJvsRhzVlAgo_36sdDtreoT9v4VynxdeyhWya6Cju7E?testcase_id=4730470358319104 See https://dev.chromium.org/Home/chromium-security/bugs/reproducing-clusterfuzz-bugs for more information. If you suspect that the result above is incorrect, try re-doing that job on the test case report page.
,
Mar 11 2017
ClusterFuzz testcase 4730470358319104 is verified as fixed, so closing issue. If this is incorrect, please add ClusterFuzz-Wrong label and re-open the issue.
,
Mar 11 2017
Probably fixed by https://chromium.googlesource.com/chromium/src/+/caf3c3acbe69ac013e2aaafad5c8110bb66e435a. There's still something to fix here, if we can still test for it.
,
Mar 11 2017
Thank you robhogan@ for the analysis, yeah, we can still crash by replacing surroundContents() with equivalent JS, or mstensho@'s case from #19 still crashes. The second case from #21 doesn't crash though.
,
Mar 11 2017
But #21 helps me a lot to understand what's happening behind. I've been wondering why clearing could make things worse. Thank you both for this much help!!
,
Mar 12 2017
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/c020f6a22577978ce1fe89fc1a397f2a651c48a8 commit c020f6a22577978ce1fe89fc1a397f2a651c48a8 Author: kojii <kojii@chromium.org> Date: Sun Mar 12 10:20:54 2017 Remove floating objects from descendants of subtree roots The pre-layout for orthogonal flow clears floats from its containing block in [1]. However, this can cause trouble for markAllDescendantsWithFloatsForLayout() to mark descendants for layout. When preceding floats overhanging to following blocks are gone, such floats are referred from multiple following blocks including descendants. Failure to mark descendants for layout may leave preceding floats. This patch ensures such floats are removed. [1] https://codereview.chromium.org/2025543002 BUG= 698455 Review-Url: https://codereview.chromium.org/2737253003 Cr-Commit-Position: refs/heads/master@{#456300} [add] https://crrev.com/c020f6a22577978ce1fe89fc1a397f2a651c48a8/third_party/WebKit/LayoutTests/fast/writing-mode/orthogonal-writing-modes-floats-crash-3.html [modify] https://crrev.com/c020f6a22577978ce1fe89fc1a397f2a651c48a8/third_party/WebKit/Source/core/frame/FrameView.cpp
,
Mar 13 2017
,
Mar 13 2017
,
Mar 14 2017
,
Mar 15 2017
,
Mar 15 2017
Your change meets the bar and is auto-approved for M58. Please go ahead and merge the CL to branch 3029 manually. Please contact milestone owner if you have questions. Owners: amineer@(Android), cmasso@(iOS), bhthompson@(ChromeOS), govind@(Desktop) For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
,
Mar 16 2017
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/285585b19c24f98a5b25d8536e5950c18db3a847 commit 285585b19c24f98a5b25d8536e5950c18db3a847 Author: Koji Ishii <kojii@chromium.org> Date: Thu Mar 16 06:59:23 2017 Merge 3029: Remove floating objects from descendants of subtree roots The pre-layout for orthogonal flow clears floats from its containing block in [1]. However, this can cause trouble for markAllDescendantsWithFloatsForLayout() to mark descendants for layout. When preceding floats overhanging to following blocks are gone, such floats are referred from multiple following blocks including descendants. Failure to mark descendants for layout may leave preceding floats. This patch ensures such floats are removed. [1] https://codereview.chromium.org/2025543002 BUG= 698455 Review-Url: https://codereview.chromium.org/2737253003 Cr-Commit-Position: refs/heads/master@{#456300} (cherry picked from commit c020f6a22577978ce1fe89fc1a397f2a651c48a8) Review-Url: https://codereview.chromium.org/2752193002 . Cr-Commit-Position: refs/branch-heads/3029@{#230} Cr-Branched-From: 939b32ee5ba05c396eef3fd992822fcca9a2e262-refs/heads/master@{#454471} [add] https://crrev.com/285585b19c24f98a5b25d8536e5950c18db3a847/third_party/WebKit/LayoutTests/fast/writing-mode/orthogonal-writing-modes-floats-crash-3.html [modify] https://crrev.com/285585b19c24f98a5b25d8536e5950c18db3a847/third_party/WebKit/Source/core/frame/FrameView.cpp
,
Mar 16 2017
Thank you Andrew.
,
Mar 16 2017
,
Jun 19 2017
This bug has been closed for more than 14 weeks. Removing security view restrictions. For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot |
|||||||||||||||||||||||||
►
Sign in to add a comment |
|||||||||||||||||||||||||
Comment 1 by vakh@chromium.org
, Mar 4 2017Owner: shend@chromium.org
Status: Assigned (was: Untriaged)