1 // Copyright 2011 The Chromium Authors
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 "net/base/io_buffer.h"
6
7 #include <utility>
8
9 #include "base/check_op.h"
10 #include "base/numerics/safe_math.h"
11
12 namespace net {
13
14 // TODO(eroman): IOBuffer is being converted to require buffer sizes and offsets
15 // be specified as "size_t" rather than "int" (crbug.com/488553). To facilitate
16 // this move (since LOTS of code needs to be updated), this function ensures
17 // that sizes can be safely converted to an "int" without truncation. The
18 // assert ensures calling this with an "int" argument is also safe.
AssertValidBufferSize(size_t size)19 void IOBuffer::AssertValidBufferSize(size_t size) {
20 static_assert(sizeof(size_t) >= sizeof(int));
21 base::CheckedNumeric<int>(size).ValueOrDie();
22 }
23
24 IOBuffer::IOBuffer() = default;
25
IOBuffer(char * data,size_t size)26 IOBuffer::IOBuffer(char* data, size_t size) : data_(data), size_(size) {
27 AssertValidBufferSize(size);
28 }
29
30 IOBuffer::~IOBuffer() = default;
31
32 IOBufferWithSize::IOBufferWithSize() = default;
33
IOBufferWithSize(size_t buffer_size)34 IOBufferWithSize::IOBufferWithSize(size_t buffer_size) {
35 AssertValidBufferSize(buffer_size);
36 if (buffer_size) {
37 size_ = buffer_size;
38 data_ = new char[buffer_size];
39 }
40 }
41
~IOBufferWithSize()42 IOBufferWithSize::~IOBufferWithSize() {
43 data_.ClearAndDeleteArray();
44 }
45
StringIOBuffer(std::string s)46 StringIOBuffer::StringIOBuffer(std::string s) : string_data_(std::move(s)) {
47 // Can't pass `s.data()` directly to IOBuffer constructor since moving
48 // from `s` may invalidate it. This is especially true for libc++ short
49 // string optimization where the data may be held in the string variable
50 // itself, instead of in a movable backing store.
51 AssertValidBufferSize(string_data_.size());
52 data_ = string_data_.data();
53 size_ = string_data_.size();
54 }
55
~StringIOBuffer()56 StringIOBuffer::~StringIOBuffer() {
57 // Clear pointer before this destructor makes it dangle.
58 data_ = nullptr;
59 }
60
DrainableIOBuffer(scoped_refptr<IOBuffer> base,size_t size)61 DrainableIOBuffer::DrainableIOBuffer(scoped_refptr<IOBuffer> base, size_t size)
62 : IOBuffer(base->data(), size), base_(std::move(base)) {}
63
DidConsume(int bytes)64 void DrainableIOBuffer::DidConsume(int bytes) {
65 SetOffset(used_ + bytes);
66 }
67
BytesRemaining() const68 int DrainableIOBuffer::BytesRemaining() const {
69 return size_ - used_;
70 }
71
72 // Returns the number of consumed bytes.
BytesConsumed() const73 int DrainableIOBuffer::BytesConsumed() const {
74 return used_;
75 }
76
SetOffset(int bytes)77 void DrainableIOBuffer::SetOffset(int bytes) {
78 CHECK_GE(bytes, 0);
79 CHECK_LE(bytes, size_);
80 used_ = bytes;
81 data_ = base_->data() + used_;
82 }
83
~DrainableIOBuffer()84 DrainableIOBuffer::~DrainableIOBuffer() {
85 // Clear ptr before this destructor destroys the |base_| instance,
86 // making it dangle.
87 data_ = nullptr;
88 }
89
90 GrowableIOBuffer::GrowableIOBuffer() = default;
91
SetCapacity(int capacity)92 void GrowableIOBuffer::SetCapacity(int capacity) {
93 CHECK_GE(capacity, 0);
94 // this will get reset in `set_offset`.
95 data_ = nullptr;
96 size_ = 0;
97
98 // realloc will crash if it fails.
99 real_data_.reset(static_cast<char*>(realloc(real_data_.release(), capacity)));
100
101 capacity_ = capacity;
102 if (offset_ > capacity)
103 set_offset(capacity);
104 else
105 set_offset(offset_); // The pointer may have changed.
106 }
107
set_offset(int offset)108 void GrowableIOBuffer::set_offset(int offset) {
109 CHECK_GE(offset, 0);
110 CHECK_LE(offset, capacity_);
111 offset_ = offset;
112 data_ = real_data_.get() + offset;
113 size_ = capacity_ - offset;
114 }
115
RemainingCapacity()116 int GrowableIOBuffer::RemainingCapacity() {
117 return capacity_ - offset_;
118 }
119
StartOfBuffer()120 char* GrowableIOBuffer::StartOfBuffer() {
121 return real_data_.get();
122 }
123
~GrowableIOBuffer()124 GrowableIOBuffer::~GrowableIOBuffer() {
125 data_ = nullptr;
126 }
127
128 PickledIOBuffer::PickledIOBuffer() = default;
129
Done()130 void PickledIOBuffer::Done() {
131 data_ = const_cast<char*>(pickle_.data_as_char());
132 size_ = pickle_.size();
133 }
134
~PickledIOBuffer()135 PickledIOBuffer::~PickledIOBuffer() {
136 // Avoid dangling ptr when this destructor destroys the pickle.
137 data_ = nullptr;
138 }
139
WrappedIOBuffer(const char * data,size_t size)140 WrappedIOBuffer::WrappedIOBuffer(const char* data, size_t size)
141 : IOBuffer(const_cast<char*>(data), size) {}
142
143 WrappedIOBuffer::~WrappedIOBuffer() = default;
144
145 } // namespace net
146