Commit message: None
CVE: CVE-2016-1647
Vulnerability description: Use-after-free vulnerability in the RenderWidgetHostImpl::Destroy function in content/browser/renderer_host/render_widget_host_impl.cc in the Navigation implementation in Google Chrome before 49.0.2623.108 allows remote attackers to cause a denial of service or possibly have unspecified other impact via unknown vectors.

Project: Chrome

bool RenderWidgetHostImpl::CanCopyFromBackingStore() {
  if (view_)
    return view_->IsSurfaceAvailableForCopy();
  return false;
}

Project: Chrome

void RenderWidgetHostImpl::DispatchColorProfile() {
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
  static bool image_profiles = base::CommandLine::ForCurrentProcess()->
     HasSwitch(switches::kEnableImageColorProfiles);
  if (!image_profiles)
    return;
#if defined(OS_WIN)
  BrowserThread::PostBlockingPoolTask(
      FROM_HERE,
      base::Bind(&RenderWidgetHostImpl::SendColorProfile,
                 weak_factory_.GetWeakPtr()));
#elif !defined(OS_CHROMEOS) && !defined(OS_IOS) && !defined(OS_ANDROID)
  SendColorProfile();
#endif
#endif
}

Project: Chrome

void RenderWidgetHostImpl::ForwardEmulatedGestureEvent(
    const blink::WebGestureEvent& gesture_event) {
  ForwardGestureEvent(gesture_event);
}

Project: Chrome

void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
      const blink::WebTouchEvent& touch_event,
      const ui::LatencyInfo& ui_latency) {
  TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardTouchEvent");


  TouchEventWithLatencyInfo touch_with_latency(touch_event, ui_latency);
  if (touch_emulator_ &&
      touch_emulator_->HandleTouchEvent(touch_with_latency.event)) {
    if (view_) {
      view_->ProcessAckedTouchEvent(
          touch_with_latency, INPUT_EVENT_ACK_STATE_CONSUMED);
    }
    return;
  }

  latency_tracker_.OnInputEvent(touch_event, &touch_with_latency.latency);
  input_router_->SendTouchEvent(touch_with_latency);
}

Project: Chrome

void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
  ui::LatencyInfo::LatencyComponent window_snapshot_component;
  if (latency_info.FindLatency(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
                               GetLatencyComponentId(),
                               &window_snapshot_component)) {
    int sequence_number = static_cast<int>(
        window_snapshot_component.sequence_number);
#if defined(OS_MACOSX)
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&RenderWidgetHostImpl::WindowSnapshotReachedScreen,
                   weak_factory_.GetWeakPtr(),
                   sequence_number),
        base::TimeDelta::FromSecondsD(1. / 6));
#else
    WindowSnapshotReachedScreen(sequence_number);
#endif
  }

  latency_tracker_.OnFrameSwapped(latency_info);
}

Project: Chrome

RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
  scoped_ptr<RenderWidgetHostIteratorImpl> hosts(
      new RenderWidgetHostIteratorImpl());
  for (auto& it : g_routing_id_widget_map.Get())
    hosts->Add(it.second);

  return std::move(hosts);
}

Project: Chrome

scoped_ptr<RenderWidgetHostIterator> RenderWidgetHost::GetRenderWidgetHosts() {
  scoped_ptr<RenderWidgetHostIteratorImpl> hosts(
      new RenderWidgetHostIteratorImpl());
  for (auto& it : g_routing_id_widget_map.Get()) {
    RenderWidgetHost* widget = it.second;

    RenderViewHost* rvh = RenderViewHost::From(widget);
    if (!rvh) {
      hosts->Add(widget);
      continue;
    }

    if (static_cast<RenderViewHostImpl*>(rvh)->is_active())
      hosts->Add(widget);
  }

  return std::move(hosts);
}

Project: Chrome

void RenderWidgetHostImpl::LostMouseLock() {
  Send(new ViewMsg_MouseLockLost(routing_id_));

  if (delegate_)
    delegate_->LostMouseLock(this);
}

Project: Chrome

void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
  color_profile_out_of_date_ = true;

  if (delegate_)
    delegate_->ScreenInfoChanged();

  WasResized();
}

Project: Chrome

void RenderWidgetHostImpl::OnHittestData(
    const FrameHostMsg_HittestData_Params& params) {
  if (delegate_)
    delegate_->GetInputEventRouter()->OnHittestData(params);
}

Project: Chrome

void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
    const gfx::Range& range,
    const std::vector<gfx::Rect>& character_bounds) {
  if (view_)
    view_->ImeCompositionRangeChanged(range, character_bounds);
}

Project: Chrome

void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
  if (!owned_by_render_frame_host_) {
    Destroy(true);
  } else {
    RendererExited(static_cast<base::TerminationStatus>(status), exit_code);
  }
}

Project: Chrome

void RenderWidgetHostImpl::OnShowDisambiguationPopup(
    const gfx::Rect& rect_pixels,
    const gfx::Size& size,
    const cc::SharedBitmapId& id) {
  DCHECK(!rect_pixels.IsEmpty());
  DCHECK(!size.IsEmpty());

  scoped_ptr<cc::SharedBitmap> bitmap =
      HostSharedBitmapManager::current()->GetSharedBitmapFromId(size, id);
  if (!bitmap) {
    bad_message::ReceivedBadMessage(GetProcess(),
                                    bad_message::RWH_SHARED_BITMAP);
    return;
  }

  DCHECK(bitmap->pixels());

  SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
  SkBitmap zoomed_bitmap;
  zoomed_bitmap.installPixels(info, bitmap->pixels(), info.minRowBytes());

  if (view_)
    view_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);

  zoomed_bitmap.setPixels(0);
  Send(new ViewMsg_ReleaseDisambiguationPopupBitmap(GetRoutingID(), id));
}

Project: Chrome

void RenderWidgetHostImpl::OnSyntheticGestureCompleted(
    SyntheticGesture::Result result) {
  Send(new InputMsg_SyntheticGestureCompleted(GetRoutingID()));
}

Project: Chrome

void RenderWidgetHostImpl::OnTouchEventAck(
    const TouchEventWithLatencyInfo& event,
    InputEventAckState ack_result) {
  latency_tracker_.OnInputEventAck(event.event, &event.latency);

  if (touch_emulator_ &&
      touch_emulator_->HandleTouchEventAck(event.event, ack_result)) {
    return;
  }

  if (view_)
    view_->ProcessAckedTouchEvent(event, ack_result);
}

Project: Chrome

void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
  waiting_for_screen_rects_ack_ = false;
  if (!view_)
    return;

  if (view_->GetViewBounds() == last_view_screen_rect_ &&
      view_->GetBoundsInRootWindow() == last_window_screen_rect_) {
    return;
  }

  SendScreenRects();
}

Project: Chrome

RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
                                           RenderProcessHost* process,
                                           int32_t routing_id,
                                           bool hidden)
    : renderer_initialized_(false),
      destroyed_(false),
      delegate_(delegate),
      owner_delegate_(nullptr),
      process_(process),
      routing_id_(routing_id),
      is_loading_(false),
      is_hidden_(hidden),
      repaint_ack_pending_(false),
      resize_ack_pending_(false),
      color_profile_out_of_date_(false),
      auto_resize_enabled_(false),
      waiting_for_screen_rects_ack_(false),
      needs_repainting_on_restore_(false),
      is_unresponsive_(false),
      in_flight_event_count_(0),
      in_get_backing_store_(false),
      ignore_input_events_(false),
      text_direction_updated_(false),
      text_direction_(blink::WebTextDirectionLeftToRight),
      text_direction_canceled_(false),
      suppress_next_char_events_(false),
      pending_mouse_lock_request_(false),
      allow_privileged_mouse_lock_(false),
      has_touch_handler_(false),
      is_in_gesture_scroll_(false),
      received_paint_after_load_(false),
      next_browser_snapshot_id_(1),
      owned_by_render_frame_host_(false),
      is_focused_(false),
      scale_input_to_viewport_(IsUseZoomForDSFEnabled()),
      hung_renderer_delay_(
          base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
      new_content_rendering_delay_(
          base::TimeDelta::FromMilliseconds(kNewContentRenderingDelayMs)),
      mouse_wheel_coalesce_timer_(new base::ElapsedTimer()),
      weak_factory_(this) {
  CHECK(delegate_);
  CHECK_NE(MSG_ROUTING_NONE, routing_id_);

  std::pair<RoutingIDWidgetMap::iterator, bool> result =
      g_routing_id_widget_map.Get().insert(std::make_pair(
          RenderWidgetHostID(process->GetID(), routing_id_), this));
  CHECK(result.second) << "Inserting a duplicate item!";
  process_->AddRoute(routing_id_, this);

  if (!hidden)
    process_->WidgetRestored();

  latency_tracker_.Initialize(routing_id_, GetProcess()->GetID());

  input_router_.reset(new InputRouterImpl(
      process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));

  touch_emulator_.reset();

  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableHangMonitor)) {
    hang_monitor_timeout_.reset(new TimeoutMonitor(
        base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive,
                   weak_factory_.GetWeakPtr())));
  }

  new_content_rendering_timeout_.reset(new TimeoutMonitor(
      base::Bind(&RenderWidgetHostImpl::ClearDisplayedGraphics,
                 weak_factory_.GetWeakPtr())));

  delegate_->RenderWidgetCreated(this);
}

Project: Chrome

void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
  Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible));
}

Project: Chrome

void RenderWidgetHostImpl::SetView(RenderWidgetHostViewBase* view) {
  if (view)
    view_ = view->GetWeakPtr();
  else
    view_.reset();

  if (view_ && renderer_initialized_) {
    Send(new ViewMsg_SetSurfaceIdNamespace(routing_id_,
                                           view_->GetSurfaceIdNamespace()));
  }

  synthetic_gesture_controller_.reset();
}

Project: Chrome

void RenderWidgetHostImpl::WaitForSurface() {
  const int kPaintMsgTimeoutMS = 50;

  if (!view_)
    return;

  gfx::Size view_size = current_size_;
  if (!auto_resize_enabled_) {
    gfx::Rect view_rect = view_->GetViewBounds();
    if (view_rect.IsEmpty())
      return;
    view_size = view_rect.size();
  }

  TRACE_EVENT2("renderer_host",
               "RenderWidgetHostImpl::WaitForSurface",
               "width",
               base::IntToString(view_size.width()),
               "height",
               base::IntToString(view_size.height()));

  DCHECK(!is_hidden_) << "WaitForSurface called while hidden!";

  DCHECK(!in_get_backing_store_) << "WaitForSurface called recursively!";
  base::AutoReset<bool> auto_reset_in_get_backing_store(
      &in_get_backing_store_, true);

  if (view_->HasAcceleratedSurface(view_size))
    return;

  if (!repaint_ack_pending_ && !resize_ack_pending_) {
    repaint_start_time_ = TimeTicks::Now();
    repaint_ack_pending_ = true;
    TRACE_EVENT_ASYNC_BEGIN0(
        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
    Send(new ViewMsg_Repaint(routing_id_, view_size));
  }

  TimeTicks start_time = TimeTicks::Now();
  TimeDelta time_left = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS);
  TimeTicks timeout_time = start_time + time_left;
  while (1) {
    TRACE_EVENT0("renderer_host", "WaitForSurface::WaitForSingleTaskToRun");
    if (ui::WindowResizeHelperMac::Get()->WaitForSingleTaskToRun(time_left)) {
      if (auto_resize_enabled_)
        view_size = current_size_;
      if (view_->HasAcceleratedSurface(view_size))
        break;
    }
    time_left = timeout_time - TimeTicks::Now();
    if (time_left <= TimeDelta::FromSeconds(0)) {
      TRACE_EVENT0("renderer_host", "WaitForSurface::Timeout");
      break;
    }
  }
}