OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 | |
15 #include "util/file/string_file_writer.h" | |
16 | |
17 #include <string.h> | |
18 | |
19 #include "base/logging.h" | |
20 #include "base/numerics/safe_math.h" | |
21 | |
22 namespace crashpad { | |
23 | |
24 StringFileWriter::StringFileWriter() : string_(), offset_(0) { | |
25 } | |
26 | |
27 StringFileWriter::~StringFileWriter() { | |
28 } | |
29 | |
30 void StringFileWriter::Reset() { | |
31 string_.clear(); | |
32 offset_ = 0; | |
33 } | |
34 | |
35 bool StringFileWriter::Write(const void* data, size_t size) { | |
36 DCHECK(offset_.IsValid()); | |
37 | |
38 size_t offset = offset_.ValueOrDie(); | |
Robert Sesek
2014/08/01 14:38:04
Mark this const so it isn't accidentally used as a
Mark Mentovai
2014/08/01 16:09:35
rsesek wrote:
| |
39 if (offset > string_.size()) { | |
40 string_.resize(offset); | |
41 } | |
42 | |
43 base::CheckedNumeric<ssize_t> new_offset = offset_; | |
44 new_offset += size; | |
45 if (!new_offset.IsValid()) { | |
46 LOG(ERROR) << "Write(): file too large"; | |
47 return false; | |
48 } | |
49 | |
50 string_.replace(offset, size, reinterpret_cast<const char*>(data), size); | |
51 offset_ = new_offset; | |
52 | |
53 return true; | |
54 } | |
55 | |
56 bool StringFileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) { | |
57 DCHECK(offset_.IsValid()); | |
58 | |
59 if (iovecs->empty()) { | |
60 LOG(ERROR) << "WriteIoVec(): no iovecs"; | |
61 return false; | |
62 } | |
63 | |
64 // Avoid writing anything at all if it would cause an overflow. | |
65 base::CheckedNumeric<ssize_t> new_offset = offset_; | |
66 for (const WritableIoVec& iov : *iovecs) { | |
67 new_offset += iov.iov_len; | |
68 if (!new_offset.IsValid()) { | |
69 LOG(ERROR) << "WriteIoVec(): file too large"; | |
70 return false; | |
71 } | |
72 } | |
73 | |
74 for (const WritableIoVec& iov : *iovecs) { | |
75 if (!Write(iov.iov_base, iov.iov_len)) { | |
76 return false; | |
77 } | |
78 } | |
79 | |
80 #ifndef NDEBUG | |
81 // The interface says that |iovecs| is not sacred, so scramble it to make sure | |
82 // that nobody depends on it. | |
83 memset(&(*iovecs)[0], 0xa5, sizeof((*iovecs)[0]) * iovecs->size()); | |
84 #endif | |
85 | |
86 return true; | |
87 } | |
88 | |
89 off_t StringFileWriter::Seek(off_t offset, int whence) { | |
90 DCHECK(offset_.IsValid()); | |
91 | |
92 size_t base_offset; | |
93 | |
94 switch (whence) { | |
95 case SEEK_SET: | |
96 base_offset = 0; | |
97 break; | |
98 | |
99 case SEEK_CUR: | |
100 base_offset = offset_.ValueOrDie(); | |
101 break; | |
102 | |
103 case SEEK_END: | |
104 base_offset = string_.size(); | |
105 break; | |
106 | |
107 default: | |
108 LOG(ERROR) << "Seek(): invalid whence " << whence; | |
109 return -1; | |
110 } | |
111 | |
112 if (!base::IsValueInRangeForNumericType<off_t>(base_offset)) { | |
113 LOG(ERROR) << "Seek(): base_offset " << base_offset << " invalid for off_t"; | |
114 return -1; | |
115 } | |
116 | |
117 base::CheckedNumeric<off_t> new_offset_checked(base_offset); | |
Robert Sesek
2014/08/01 14:38:04
Could use AssignIfInRange() for lines 112-117.
Mark Mentovai
2014/08/01 16:09:35
rsesek wrote:
| |
118 new_offset_checked += offset; | |
119 if (!new_offset_checked.IsValid()) { | |
120 LOG(ERROR) << "Seek(): new_offset invalid"; | |
121 return -1; | |
122 } | |
123 | |
124 off_t new_offset = new_offset_checked.ValueOrDie(); | |
125 if (!base::IsValueInRangeForNumericType<size_t>(new_offset)) { | |
Robert Sesek
2014/08/01 14:38:04
Same.
| |
126 LOG(ERROR) << "Seek(): new_offset " << new_offset << " invalid for size_t"; | |
127 return -1; | |
128 } | |
129 | |
130 offset_ = new_offset; | |
131 | |
132 return offset_.ValueOrDie(); | |
133 } | |
134 | |
135 } // namespace crashpad | |
OLD | NEW |