Commit message: None
CVE: CVE-2013-0920
CWE: CWE-399
Vulnerability description: Use-after-free vulnerability in the extension bookmarks API in Google Chrome before 26.0.1410.43 allows remote attackers to cause a denial of service or possibly have unspecified other impact via unknown vectors.

Project: Chrome

void BookmarkEventRouter::BookmarkNodeChanged(BookmarkModel* model,
                                              const BookmarkNode* node) {
  scoped_ptr<ListValue> args(new ListValue());
  args->Append(new StringValue(base::Int64ToString(node->id())));

  DictionaryValue* object_args = new DictionaryValue();
  object_args->SetString(keys::kTitleKey, node->GetTitle());
  if (node->is_url())
    object_args->SetString(keys::kUrlKey, node->url().spec());
  args->Append(object_args);

  DispatchEvent(model->profile(), keys::kOnBookmarkChanged, args.Pass());
}

Project: Chrome

void BookmarkEventRouter::BookmarkNodeChildrenReordered(
    BookmarkModel* model,
    const BookmarkNode* node) {
  scoped_ptr<ListValue> args(new ListValue());
  args->Append(new StringValue(base::Int64ToString(node->id())));
  int childCount = node->child_count();
  ListValue* children = new ListValue();
  for (int i = 0; i < childCount; ++i) {
    const BookmarkNode* child = node->GetChild(i);
    Value* child_id = new StringValue(base::Int64ToString(child->id()));
    children->Append(child_id);
  }
  DictionaryValue* reorder_info = new DictionaryValue();
  reorder_info->Set(keys::kChildIdsKey, children);
  args->Append(reorder_info);

  DispatchEvent(model->profile(), keys::kOnBookmarkChildrenReordered,
                args.Pass());
}

Project: Chrome

  explicit CreateBookmarkBucketMapper(Profile* profile) : profile_(profile) {}

Project: Chrome

void BookmarksUpdateFunction::GetQuotaLimitHeuristics(
    QuotaLimitHeuristics* heuristics) const {
  BookmarksQuotaLimitFactory::Build<BookmarksUpdateFunction>(heuristics);
};

Project: Chrome

void BookmarksFunction::Run() {
  BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
  if (!model->IsLoaded()) {
    model->AddObserver(this);
    AddRef();  // Balanced in Loaded().
    return;
  }

  bool success = RunImpl();
  if (success) {
    content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_EXTENSION_BOOKMARKS_API_INVOKED,
        content::Source<const Extension>(GetExtension()),
        content::Details<const BookmarksFunction>(this));
  }
  SendResponse(success);
}

Project: Chrome

bool BookmarksGetRecentFunction::RunImpl() {
  scoped_ptr<bookmarks::GetSubTree::Params> params(
      bookmarks::GetSubTree::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  int64 id;
  if (!GetBookmarkIdAsInt64(params->id, &id))
    return false;

  const BookmarkNode* node =
      BookmarkModelFactory::GetForProfile(profile())->GetNodeByID(id);
  if (!node) {
    error_ = keys::kNoNodeError;
    return false;
  }

  std::vector<linked_ptr<BookmarkTreeNode> > nodes;
  bookmark_api_helpers::AddNode(node, &nodes, true);
  results_ = bookmarks::GetSubTree::Results::Create(nodes);
  return true;
}

Project: Chrome

bool BookmarksRemoveFunction::RunImpl() {
  if (!EditBookmarksEnabled())
    return false;

  scoped_ptr<bookmarks::Remove::Params> params(
      bookmarks::Remove::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  int64 id;
  if (!base::StringToInt64(params->id, &id)) {
    error_ = keys::kInvalidIdError;
    return false;
  }

  bool recursive = false;
  if (name() == BookmarksRemoveTreeFunction::function_name())
    recursive = true;

  BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
  if (!bookmark_api_helpers::RemoveNode(model, id, recursive, &error_))
    return false;

  return true;
}

Project: Chrome

bool BookmarksUpdateFunction::RunImpl() {
  if (!EditBookmarksEnabled())
    return false;

  scoped_ptr<bookmarks::Update::Params> params(
      bookmarks::Update::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  int64 id;
  if (!base::StringToInt64(params->id, &id)) {
    error_ = keys::kInvalidIdError;
    return false;
  }

  BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());

  string16 title;
  bool has_title = false;
  if (params->changes.title.get()) {
    title = UTF8ToUTF16(*params->changes.title);
    has_title = true;
  }

  std::string url_string;
  if (params->changes.url.get())
    url_string = *params->changes.url;
  GURL url(url_string);
  if (!url_string.empty() && !url.is_valid()) {
    error_ = keys::kInvalidUrlError;
    return false;
  }

  const BookmarkNode* node = model->GetNodeByID(id);
  if (!node) {
    error_ = keys::kNoNodeError;
    return false;
  }
  if (model->is_permanent_node(node)) {
    error_ = keys::kModifySpecialError;
    return false;
  }
  if (has_title)
    model->SetTitle(node, title);
  if (!url.is_empty())
    model->SetURL(node, url);

  scoped_ptr<BookmarkTreeNode> tree_node(
      bookmark_api_helpers::GetBookmarkTreeNode(node, false, false));
  results_ = bookmarks::Update::Results::Create(*tree_node);
  return true;
}

Project: Chrome

bool BookmarksExportFunction::RunImpl() {
  SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE);
  return true;
}

Project: Chrome

BookmarkEventRouter::~BookmarkEventRouter() {
  if (model_) {
    model_->RemoveObserver(this);
  }
}