Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: mojo/public/cpp/bindings/lib/bounds_checker.cc

Issue 289333002: Mojo cpp bindings: validation logic for incoming messages (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mojo/public/cpp/bindings/lib/bounds_checker.h"
6
7 #include <assert.h>
8
9 #include <algorithm>
10
11 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
12 #include "mojo/public/cpp/system/core.h"
13
14 namespace mojo {
15 namespace internal {
16 namespace {
17
18 bool IsClaimedRangesVectorValid(const std::vector<uintptr_t>& claimed_ranges) {
19 if (claimed_ranges.empty())
20 return true;
21
22 if (claimed_ranges.size() % 2)
23 return false;
24
25 for (std::vector<uintptr_t>::const_iterator iter = claimed_ranges.begin() + 1;
26 iter != claimed_ranges.end();
27 ++iter) {
28 if (*(iter - 1) >= *iter)
29 return false;
30 }
31 return true;
32 }
33
34 } // namespace
35
36 BoundsChecker::BoundsChecker(const void* data, uint32_t data_num_bytes,
37 size_t num_handles)
38 : data_begin_(reinterpret_cast<uintptr_t>(data)),
39 data_end_(data_begin_ + data_num_bytes),
40 claimed_handles_(num_handles, false) {
41 if (data_end_ < data_begin_) {
42 // The calculation of |data_end_| overflowed.
43 // It shouldn't happen but if it does, set the range to empty so
44 // IsWithinBounds() and ClaimMemory() always fail.
45 assert(false); // Not reached.
46 data_end_ = data_begin_;
47 }
48 }
49
50 BoundsChecker::~BoundsChecker() {
51 assert(IsClaimedRangesVectorValid(claimed_ranges_));
52 }
53
54 bool BoundsChecker::ClaimMemory(const void* position, uint32_t num_bytes) {
55 uintptr_t begin = reinterpret_cast<uintptr_t>(position);
56 uintptr_t end = begin + num_bytes;
57
58 if (!InternalIsWithinBounds(begin, end))
59 return false;
60
61 if (claimed_ranges_.empty() || begin >= claimed_ranges_.back()) {
62 // This optimization is significant: if the layout of objects in an incoming
63 // message are in the same order as our validation code traverses the
64 // message, we will always hit this code path.
65 InsertOrMergeClaimedRange(claimed_ranges_.end(), begin, end);
66 return true;
67 }
68
69 // Find |iter| which pointers to the first element that is greater than
70 // |begin|. (The previous if-block guarantees that such an element must exist
71 // if we reach this point.)
72 std::vector<uintptr_t>::iterator iter = std::upper_bound(
73 claimed_ranges_.begin(), claimed_ranges_.end(), begin);
74 assert(iter != claimed_ranges_.end());
75
76 // If the corresponding index of |iter| is an odd number, |begin| lies in a
77 // claimed range.
78 if ((iter - claimed_ranges_.begin()) % 2)
79 return false;
80 // If |end| is bigger than |*iter| while |begin| is smaller, then [begin, end)
81 // overlaps at least one claimed range.
82 if (end > *iter)
83 return false;
84
85 InsertOrMergeClaimedRange(iter, begin, end);
86 return true;
87 }
88
89 bool BoundsChecker::ClaimHandle(const Handle& encoded_handle) {
90 uint32_t index = encoded_handle.value();
91 if (index == kEncodedInvalidHandleValue)
92 return true;
93
94 if (index >= claimed_handles_.size() || claimed_handles_[index])
95 return false;
96
97 claimed_handles_[index] = true;
98 return true;
99 }
100
101 bool BoundsChecker::IsWithinBounds(const void* position,
102 uint32_t num_bytes) const {
103 uintptr_t begin = reinterpret_cast<uintptr_t>(position);
104 uintptr_t end = begin + num_bytes;
105
106 return InternalIsWithinBounds(begin, end);
107 }
108
109 const std::vector<uintptr_t>&
110 BoundsChecker::GetClaimedRangesForTesting() const {
111 return claimed_ranges_;
112 }
113
114 void BoundsChecker::InsertOrMergeClaimedRange(
115 std::vector<uintptr_t>::iterator pos, uintptr_t begin, uintptr_t end) {
116 bool merge_previous = pos != claimed_ranges_.begin() &&
117 *(pos - 1) == begin;
118 bool merge_next = pos != claimed_ranges_.end() &&
119 *pos == end;
120
121 if (merge_previous && merge_next) {
122 *(pos - 1) = *(pos + 1);
123 claimed_ranges_.erase(pos, pos + 2);
124 } else if (merge_previous) {
125 *(pos - 1) = end;
126 } else if (merge_next) {
127 *pos = begin;
128 } else {
129 uintptr_t pair[2] = {begin, end};
130 claimed_ranges_.insert(pos, pair, pair + 2);
131 }
132 }
133
134 bool BoundsChecker::InternalIsWithinBounds(uintptr_t begin,
135 uintptr_t end) const {
136 return end > begin && begin >= data_begin_ && end <= data_end_;
137 }
138
139 } // namespace internal
140 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698