bounds_checker.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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 "mojo/public/cpp/bindings/lib/bindings_serialization.h"
10#include "mojo/public/cpp/system/core.h"
11
12namespace mojo {
13namespace internal {
14
15BoundsChecker::BoundsChecker(const void* data, uint32_t data_num_bytes,
16                             size_t num_handles)
17    : data_begin_(reinterpret_cast<uintptr_t>(data)),
18      data_end_(data_begin_ + data_num_bytes),
19      handle_begin_(0),
20      handle_end_(static_cast<uint32_t>(num_handles)) {
21  if (data_end_ < data_begin_) {
22    // The calculation of |data_end_| overflowed.
23    // It shouldn't happen but if it does, set the range to empty so
24    // IsValidRange() and ClaimMemory() always fail.
25    assert(false);  // Not reached.
26    data_end_ = data_begin_;
27  }
28  if (handle_end_ < num_handles) {
29    // Assigning |num_handles| to |handle_end_| overflowed.
30    // It shouldn't happen but if it does, set the handle index range to empty.
31    assert(false);  // Not reached.
32    handle_end_ = 0;
33  }
34}
35
36BoundsChecker::~BoundsChecker() {
37}
38
39bool BoundsChecker::ClaimMemory(const void* position, uint32_t num_bytes) {
40  uintptr_t begin = reinterpret_cast<uintptr_t>(position);
41  uintptr_t end = begin + num_bytes;
42
43  if (!InternalIsValidRange(begin, end))
44    return false;
45
46  data_begin_ = end;
47  return true;
48}
49
50bool BoundsChecker::ClaimHandle(const Handle& encoded_handle) {
51  uint32_t index = encoded_handle.value();
52  if (index == kEncodedInvalidHandleValue)
53    return true;
54
55  if (index < handle_begin_ || index >= handle_end_)
56    return false;
57
58  // |index| + 1 shouldn't overflow, because |index| is not the max value of
59  // uint32_t (it is less than |handle_end_|).
60  handle_begin_ = index + 1;
61  return true;
62}
63
64bool BoundsChecker::IsValidRange(const void* position,
65                                 uint32_t num_bytes) const {
66  uintptr_t begin = reinterpret_cast<uintptr_t>(position);
67  uintptr_t end = begin + num_bytes;
68
69  return InternalIsValidRange(begin, end);
70}
71
72bool BoundsChecker::InternalIsValidRange(uintptr_t begin, uintptr_t end) const {
73  return end > begin && begin >= data_begin_ && end <= data_end_;
74}
75
76}  // namespace internal
77}  // namespace mojo
78