mirror of
https://github.com/chromium/crashpad.git
synced 2025-01-04 04:35:26 +08:00
6e720f1421
The final range check needs to check that the value fits in a size_t, because that’s what StringFileWriter uses for its offset_. TEST=util_test StringFileWriter.SeekInvalid R=rsesek@chromium.org Review URL: https://codereview.chromium.org/434103003
138 lines
3.4 KiB
C++
138 lines
3.4 KiB
C++
// Copyright 2014 The Crashpad Authors. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "util/file/string_file_writer.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "base/logging.h"
|
|
#include "base/numerics/safe_math.h"
|
|
#include "util/numeric/safe_assignment.h"
|
|
|
|
namespace crashpad {
|
|
|
|
StringFileWriter::StringFileWriter() : string_(), offset_(0) {
|
|
}
|
|
|
|
StringFileWriter::~StringFileWriter() {
|
|
}
|
|
|
|
void StringFileWriter::Reset() {
|
|
string_.clear();
|
|
offset_ = 0;
|
|
}
|
|
|
|
bool StringFileWriter::Write(const void* data, size_t size) {
|
|
DCHECK(offset_.IsValid());
|
|
|
|
const size_t offset = offset_.ValueOrDie();
|
|
if (offset > string_.size()) {
|
|
string_.resize(offset);
|
|
}
|
|
|
|
base::CheckedNumeric<ssize_t> new_offset = offset_;
|
|
new_offset += size;
|
|
if (!new_offset.IsValid()) {
|
|
LOG(ERROR) << "Write(): file too large";
|
|
return false;
|
|
}
|
|
|
|
string_.replace(offset, size, reinterpret_cast<const char*>(data), size);
|
|
offset_ = new_offset;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool StringFileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) {
|
|
DCHECK(offset_.IsValid());
|
|
|
|
if (iovecs->empty()) {
|
|
LOG(ERROR) << "WriteIoVec(): no iovecs";
|
|
return false;
|
|
}
|
|
|
|
// Avoid writing anything at all if it would cause an overflow.
|
|
base::CheckedNumeric<ssize_t> new_offset = offset_;
|
|
for (const WritableIoVec& iov : *iovecs) {
|
|
new_offset += iov.iov_len;
|
|
if (!new_offset.IsValid()) {
|
|
LOG(ERROR) << "WriteIoVec(): file too large";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for (const WritableIoVec& iov : *iovecs) {
|
|
if (!Write(iov.iov_base, iov.iov_len)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
// The interface says that |iovecs| is not sacred, so scramble it to make sure
|
|
// that nobody depends on it.
|
|
memset(&(*iovecs)[0], 0xa5, sizeof((*iovecs)[0]) * iovecs->size());
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
off_t StringFileWriter::Seek(off_t offset, int whence) {
|
|
DCHECK(offset_.IsValid());
|
|
|
|
size_t base_offset;
|
|
|
|
switch (whence) {
|
|
case SEEK_SET:
|
|
base_offset = 0;
|
|
break;
|
|
|
|
case SEEK_CUR:
|
|
base_offset = offset_.ValueOrDie();
|
|
break;
|
|
|
|
case SEEK_END:
|
|
base_offset = string_.size();
|
|
break;
|
|
|
|
default:
|
|
LOG(ERROR) << "Seek(): invalid whence " << whence;
|
|
return -1;
|
|
}
|
|
|
|
off_t base_offset_offt;
|
|
if (!AssignIfInRange(&base_offset_offt, base_offset)) {
|
|
LOG(ERROR) << "Seek(): base_offset " << base_offset << " invalid for off_t";
|
|
return -1;
|
|
}
|
|
base::CheckedNumeric<off_t> new_offset(base_offset_offt);
|
|
new_offset += offset;
|
|
if (!new_offset.IsValid()) {
|
|
LOG(ERROR) << "Seek(): new_offset invalid";
|
|
return -1;
|
|
}
|
|
off_t new_offset_offt = new_offset.ValueOrDie();
|
|
size_t new_offset_sizet;
|
|
if (!AssignIfInRange(&new_offset_sizet, new_offset_offt)) {
|
|
LOG(ERROR) << "Seek(): new_offset " << new_offset_offt
|
|
<< " invalid for size_t";
|
|
return -1;
|
|
}
|
|
|
|
offset_ = new_offset_sizet;
|
|
|
|
return offset_.ValueOrDie();
|
|
}
|
|
|
|
} // namespace crashpad
|