Commit message: None
CVE: CVE-2014-3191
CWE: CWE-416
Vulnerability description: Use-after-free vulnerability in Blink, as used in Google Chrome before 38.0.2125.101, allows remote attackers to cause a denial of service or possibly have unspecified other impact via crafted JavaScript code that triggers a widget-position update that improperly interacts with the render tree, related to the FrameView::updateLayoutAndStyleForPainting function in core/frame/FrameView.cpp and the RenderLayerScrollableArea::setScrollOffset function in core/rendering/RenderLayerScrollableArea.cpp.

Project: Chrome

 void FrameView::updateLayoutAndStyleForPainting()
 {
     RefPtr<FrameView> protector(this);
 
     updateLayoutAndStyleIfNeededRecursive();
 
     if (RenderView* view = renderView()) {
         TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateLayerTree", "frame", m_frame.get());
        InspectorInstrumentation::willUpdateLayerTree(m_frame.get());

        view->compositor()->updateIfNeededRecursive();

        if (view->compositor()->inCompositingMode() && m_frame->isLocalRoot())
            m_frame->page()->scrollingCoordinator()->updateAfterCompositingChangeIfNeeded();

        updateCompositedSelectionBoundsIfNeeded();

        InspectorInstrumentation::didUpdateLayerTree(m_frame.get());

        invalidateTreeIfNeededRecursive();
    }

    scrollContentsIfNeededRecursive();
    ASSERT(lifecycle().state() == DocumentLifecycle::PaintInvalidationClean);
}

Project: Chrome

void RenderLayerScrollableArea::setScrollOffset(const IntPoint& newScrollOffset)
{
    if (!box().isMarquee()) {
        if (m_scrollDimensionsDirty)
            computeScrollDimensions();
    }

    if (scrollOffset() == toIntSize(newScrollOffset))
        return;

    setScrollOffset(toIntSize(newScrollOffset));

    LocalFrame* frame = box().frame();
    ASSERT(frame);

    RefPtr<FrameView> frameView = box().frameView();

    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ScrollLayer", "data", InspectorScrollLayerEvent::data(&box()));
    InspectorInstrumentation::willScrollLayer(&box());

    const RenderLayerModelObject* paintInvalidationContainer = box().containerForPaintInvalidation();

    if (!frameView->isInPerformLayout()) {
        layer()->clipper().clearClipRectsIncludingDescendants();
         box().setPreviousPaintInvalidationRect(box().boundsRectForPaintInvalidation(paintInvalidationContainer));
         frameView->updateAnnotatedRegions();
        frameView->updateWidgetPositions();
        RELEASE_ASSERT(frameView->renderView());
         updateCompositingLayersAfterScroll();
     }
 
    frame->selection().setCaretRectNeedsUpdate();

    FloatQuad quadForFakeMouseMoveEvent = FloatQuad(layer()->renderer()->previousPaintInvalidationRect());

    quadForFakeMouseMoveEvent = paintInvalidationContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
    frame->eventHandler().dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);

    bool requiresPaintInvalidation = true;

    if (!box().isMarquee() && box().view()->compositor()->inCompositingMode()) {
        DisableCompositingQueryAsserts disabler;
        bool onlyScrolledCompositedLayers = scrollsOverflow()
            && !layer()->hasVisibleNonLayerContent()
            && !layer()->hasNonCompositedChild()
            && !layer()->hasBlockSelectionGapBounds()
            && box().style()->backgroundLayers().attachment() != LocalBackgroundAttachment;

        if (usesCompositedScrolling() || onlyScrolledCompositedLayers)
            requiresPaintInvalidation = false;
    }

    if (requiresPaintInvalidation) {
        if (box().frameView()->isInPerformLayout())
            box().setShouldDoFullPaintInvalidation(true);
        else
            box().invalidatePaintUsingContainer(paintInvalidationContainer, layer()->renderer()->previousPaintInvalidationRect(), InvalidationScroll);
    }

    if (box().node())
        box().node()->document().enqueueScrollEventForNode(box().node());

    if (AXObjectCache* cache = box().document().existingAXObjectCache())
        cache->handleScrollPositionChanged(&box());

    InspectorInstrumentation::didScrollLayer(&box());
}