Skip to content

Commit 5353de1

Browse files
dhveerapmibrunin
authored andcommitted
[Backport] CVE-2021-30518: Heap buffer overflow in Reader Mode
Cherry-pick of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/2856118: Replace std::vector with base::ObserverList to support container modification while iterating TaskTracker saves list of viewers in vector, that needs to be notified when distillation is completed. At the time of notifying the viewers, we are indirectly erasing viewers from vector while iterating. This is causing container-overflow in asan build when vector has more than one viewer while notifying. This change is to replace vector with ObserverList that can be modified during iteration without invalidating the iterator. Bug: 1203590 Change-Id: I7c7b8237584c48c9ebc2639b9268a6a78c2db4b2 Reviewed-by: Matt Jones <[email protected]> Commit-Queue: Akhila Veerapuraju <[email protected]> Cr-Commit-Position: refs/heads/master@{#877492} Reviewed-by: Allan Sandfeld Jensen <[email protected]>
1 parent 4646e31 commit 5353de1

File tree

2 files changed

+10
-9
lines changed

2 files changed

+10
-9
lines changed

chromium/components/dom_distiller/core/task_tracker.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void TaskTracker::AddSaveCallback(SaveCallback callback) {
8585

8686
std::unique_ptr<ViewerHandle> TaskTracker::AddViewer(
8787
ViewRequestDelegate* delegate) {
88-
viewers_.push_back(delegate);
88+
viewers_.AddObserver(delegate);
8989
if (content_ready_) {
9090
// Distillation for this task has already completed, and so the delegate can
9191
// be immediately told of the result.
@@ -115,7 +115,7 @@ bool TaskTracker::HasUrl(const GURL& url) const {
115115
}
116116

117117
void TaskTracker::RemoveViewer(ViewRequestDelegate* delegate) {
118-
base::Erase(viewers_, delegate);
118+
viewers_.RemoveObserver(delegate);
119119
if (viewers_.empty()) {
120120
MaybeCancel();
121121
}
@@ -219,8 +219,8 @@ void TaskTracker::DistilledArticleReady(
219219
}
220220

221221
void TaskTracker::NotifyViewersAndCallbacks() {
222-
for (auto* viewer : viewers_) {
223-
NotifyViewer(viewer);
222+
for (auto& viewer : viewers_) {
223+
NotifyViewer(&viewer);
224224
}
225225

226226
// Already inside a callback run SaveCallbacks directly.
@@ -242,8 +242,8 @@ void TaskTracker::DoSaveCallbacks(bool success) {
242242

243243
void TaskTracker::OnArticleDistillationUpdated(
244244
const ArticleDistillationUpdate& article_update) {
245-
for (auto* viewer : viewers_) {
246-
viewer->OnArticleUpdated(article_update);
245+
for (auto& viewer : viewers_) {
246+
viewer.OnArticleUpdated(article_update);
247247
}
248248
}
249249

chromium/components/dom_distiller/core/task_tracker.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "base/bind.h"
1212
#include "base/callback.h"
1313
#include "base/memory/weak_ptr.h"
14+
#include "base/observer_list.h"
1415
#include "components/dom_distiller/core/article_distillation_update.h"
1516
#include "components/dom_distiller/core/article_entry.h"
1617
#include "components/dom_distiller/core/distiller.h"
@@ -40,9 +41,9 @@ class ViewerHandle {
4041

4142
// Interface for a DOM distiller entry viewer. Implement this to make a view
4243
// request and receive the data for an entry when it becomes available.
43-
class ViewRequestDelegate {
44+
class ViewRequestDelegate : public base::CheckedObserver {
4445
public:
45-
virtual ~ViewRequestDelegate() = default;
46+
~ViewRequestDelegate() override = default;
4647

4748
// Called when the distilled article contents are available. The
4849
// DistilledArticleProto is owned by a TaskTracker instance and is invalidated
@@ -140,7 +141,7 @@ class TaskTracker {
140141
std::vector<SaveCallback> save_callbacks_;
141142
// A ViewRequestDelegate will be added to this list when a view request is
142143
// made and removed when the corresponding ViewerHandle is destroyed.
143-
std::vector<ViewRequestDelegate*> viewers_;
144+
base::ObserverList<ViewRequestDelegate> viewers_;
144145

145146
std::unique_ptr<Distiller> distiller_;
146147
bool blob_fetcher_running_;

0 commit comments

Comments
 (0)