win: Resolve zero-length array errors on MSVC

In some cases, it's sufficient to move the zero-length array to the end of the
structure. When the struct is used inside a class that is derived from however,
this fails. In that case, switch to holding the object in a scoped_ptr.

Longer winded version: https://groups.google.com/a/chromium.org/d/msg/crashpad-dev/NGZ6LwRMORM/nKcXKQ7inIEJ

R=mark@chromium.org
BUG=crashpad:1

Review URL: https://codereview.chromium.org/896663006
This commit is contained in:
Scott Graham 2015-02-04 17:34:43 -08:00
parent 429a3368d4
commit 74a34e9c4b
15 changed files with 45 additions and 29 deletions

View File

@ -24,6 +24,16 @@
#include "build/build_config.h"
#include "util/misc/uuid.h"
#if defined(COMPILER_MSVC)
// C4200 is "nonstandard extension used : zero-sized array in struct/union".
// We would like to globally disable this warning, but unfortunately, the
// compiler is buggy and only supports disabling it with a pragma, so we can't
// disable it with other silly warnings in build/common.gypi. See:
// https://connect.microsoft.com/VisualStudio/feedback/details/1114440
#pragma warning(push)
#pragma warning(disable: 4200)
#endif // COMPILER_MSVC
#if defined(COMPILER_MSVC)
#define PACKED
#pragma pack(push, 1)
@ -460,6 +470,10 @@ struct ALIGNAS(4) PACKED MinidumpCrashpadInfo {
#endif // COMPILER_MSVC
#undef PACKED
#if defined(COMPILER_MSVC)
#pragma warning(pop) // C4200
#endif // COMPILER_MSVC
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_EXTENSIONS_H_

View File

@ -23,7 +23,7 @@ namespace internal {
MinidumpLocationDescriptorListWriter::MinidumpLocationDescriptorListWriter()
: MinidumpWritable(),
location_descriptor_list_base_(),
location_descriptor_list_base_(new MinidumpLocationDescriptorList()),
children_(),
child_location_descriptors_() {
}
@ -47,7 +47,8 @@ bool MinidumpLocationDescriptorListWriter::Freeze() {
}
size_t child_count = children_.size();
if (!AssignIfInRange(&location_descriptor_list_base_.count, child_count)) {
if (!AssignIfInRange(&location_descriptor_list_base_->count,
child_count)) {
LOG(ERROR) << "child_count " << child_count << " out of range";
return false;
}
@ -64,7 +65,7 @@ bool MinidumpLocationDescriptorListWriter::Freeze() {
size_t MinidumpLocationDescriptorListWriter::SizeOfObject() {
DCHECK_GE(state(), kStateFrozen);
return sizeof(location_descriptor_list_base_) +
return sizeof(*location_descriptor_list_base_) +
children_.size() * sizeof(MINIDUMP_LOCATION_DESCRIPTOR);
}
@ -86,8 +87,8 @@ bool MinidumpLocationDescriptorListWriter::WriteObject(
DCHECK_EQ(children_.size(), child_location_descriptors_.size());
WritableIoVec iov;
iov.iov_base = &location_descriptor_list_base_;
iov.iov_len = sizeof(location_descriptor_list_base_);
iov.iov_base = location_descriptor_list_base_.get();
iov.iov_len = sizeof(*location_descriptor_list_base_);
std::vector<WritableIoVec> iovecs(1, iov);
if (!child_location_descriptors_.empty()) {

View File

@ -70,7 +70,7 @@ class MinidumpLocationDescriptorListWriter : public MinidumpWritable {
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MinidumpLocationDescriptorList location_descriptor_list_base_;
scoped_ptr<MinidumpLocationDescriptorList> location_descriptor_list_base_;
PointerVector<MinidumpWritable> children_;
std::vector<MINIDUMP_LOCATION_DESCRIPTOR> child_location_descriptors_;

View File

@ -162,9 +162,9 @@ internal::MinidumpWritable::Phase MinidumpMemoryWriter::WritePhase() {
MinidumpMemoryListWriter::MinidumpMemoryListWriter()
: MinidumpStreamWriter(),
memory_list_base_(),
memory_writers_(),
children_() {
children_(),
memory_list_base_() {
}
MinidumpMemoryListWriter::~MinidumpMemoryListWriter() {

View File

@ -180,9 +180,9 @@ class MinidumpMemoryListWriter final : public internal::MinidumpStreamWriter {
MinidumpStreamType StreamType() const override;
private:
MINIDUMP_MEMORY_LIST memory_list_base_;
std::vector<MinidumpMemoryWriter*> memory_writers_; // weak
PointerVector<MinidumpMemoryWriter> children_;
MINIDUMP_MEMORY_LIST memory_list_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryListWriter);
};

View File

@ -375,7 +375,7 @@ bool MinidumpModuleWriter::WriteObject(FileWriterInterface* file_writer) {
}
MinidumpModuleListWriter::MinidumpModuleListWriter()
: MinidumpStreamWriter(), module_list_base_(), modules_() {
: MinidumpStreamWriter(), modules_(), module_list_base_() {
}
MinidumpModuleListWriter::~MinidumpModuleListWriter() {

View File

@ -346,8 +346,8 @@ class MinidumpModuleListWriter final : public internal::MinidumpStreamWriter {
MinidumpStreamType StreamType() const override;
private:
MINIDUMP_MODULE_LIST module_list_base_;
PointerVector<MinidumpModuleWriter> modules_;
MINIDUMP_MODULE_LIST module_list_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleListWriter);
};

View File

@ -23,7 +23,7 @@ namespace internal {
MinidumpRVAListWriter::MinidumpRVAListWriter()
: MinidumpWritable(),
rva_list_base_(),
rva_list_base_(new MinidumpRVAList()),
children_(),
child_rvas_() {
}
@ -46,7 +46,7 @@ bool MinidumpRVAListWriter::Freeze() {
}
size_t child_count = children_.size();
if (!AssignIfInRange(&rva_list_base_.count, child_count)) {
if (!AssignIfInRange(&rva_list_base_->count, child_count)) {
LOG(ERROR) << "child_count " << child_count << " out of range";
return false;
}
@ -62,7 +62,7 @@ bool MinidumpRVAListWriter::Freeze() {
size_t MinidumpRVAListWriter::SizeOfObject() {
DCHECK_GE(state(), kStateFrozen);
return sizeof(rva_list_base_) + children_.size() * sizeof(RVA);
return sizeof(*rva_list_base_) + children_.size() * sizeof(RVA);
}
std::vector<MinidumpWritable*> MinidumpRVAListWriter::Children() {
@ -81,8 +81,8 @@ bool MinidumpRVAListWriter::WriteObject(FileWriterInterface* file_writer) {
DCHECK_EQ(children_.size(), child_rvas_.size());
WritableIoVec iov;
iov.iov_base = &rva_list_base_;
iov.iov_len = sizeof(rva_list_base_);
iov.iov_base = rva_list_base_.get();
iov.iov_len = sizeof(*rva_list_base_);
std::vector<WritableIoVec> iovecs(1, iov);
if (!child_rvas_.empty()) {

View File

@ -66,7 +66,7 @@ class MinidumpRVAListWriter : public MinidumpWritable {
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MinidumpRVAList rva_list_base_;
scoped_ptr<MinidumpRVAList> rva_list_base_;
PointerVector<MinidumpWritable> children_;
std::vector<RVA> child_rvas_;

View File

@ -91,7 +91,7 @@ bool MinidumpSimpleStringDictionaryEntryWriter::WriteObject(
}
MinidumpSimpleStringDictionaryWriter::MinidumpSimpleStringDictionaryWriter()
: MinidumpWritable(), simple_string_dictionary_base_(), entries_() {
: MinidumpWritable(), entries_(), simple_string_dictionary_base_() {
}
MinidumpSimpleStringDictionaryWriter::~MinidumpSimpleStringDictionaryWriter() {

View File

@ -132,11 +132,11 @@ class MinidumpSimpleStringDictionaryWriter final
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MinidumpSimpleStringDictionary simple_string_dictionary_base_;
// This object owns the MinidumpSimpleStringDictionaryEntryWriter objects.
std::map<std::string, MinidumpSimpleStringDictionaryEntryWriter*> entries_;
MinidumpSimpleStringDictionary simple_string_dictionary_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpSimpleStringDictionaryWriter);
};

View File

@ -26,7 +26,7 @@ namespace internal {
template <typename Traits>
MinidumpStringWriter<Traits>::MinidumpStringWriter()
: MinidumpWritable(), string_base_(), string_() {
: MinidumpWritable(), string_base_(new MinidumpStringType()), string_() {
}
template <typename Traits>
@ -42,7 +42,7 @@ bool MinidumpStringWriter<Traits>::Freeze() {
}
size_t string_bytes = string_.size() * sizeof(string_[0]);
if (!AssignIfInRange(&string_base_.Length, string_bytes)) {
if (!AssignIfInRange(&string_base_->Length, string_bytes)) {
LOG(ERROR) << "string_bytes " << string_bytes << " out of range";
return false;
}
@ -55,7 +55,7 @@ size_t MinidumpStringWriter<Traits>::SizeOfObject() {
DCHECK_GE(state(), kStateFrozen);
// Include the NUL terminator.
return sizeof(string_base_) + (string_.size() + 1) * sizeof(string_[0]);
return sizeof(*string_base_) + (string_.size() + 1) * sizeof(string_[0]);
}
template <typename Traits>
@ -66,8 +66,8 @@ bool MinidumpStringWriter<Traits>::WriteObject(
// The strings length is stored in string_base_, and its data is stored in
// string_. Write them both.
WritableIoVec iov;
iov.iov_base = &string_base_;
iov.iov_len = sizeof(string_base_);
iov.iov_base = string_base_.get();
iov.iov_len = sizeof(*string_base_);
std::vector<WritableIoVec> iovecs(1, iov);
// Include the NUL terminator.

View File

@ -22,6 +22,7 @@
#include <vector>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_rva_list_writer.h"
@ -75,7 +76,7 @@ class MinidumpStringWriter : public MinidumpWritable {
const StringType& string() const { return string_; }
private:
MinidumpStringType string_base_;
scoped_ptr<MinidumpStringType> string_base_;
StringType string_;
DISALLOW_COPY_AND_ASSIGN(MinidumpStringWriter);

View File

@ -129,9 +129,9 @@ bool MinidumpThreadWriter::WriteObject(FileWriterInterface* file_writer) {
MinidumpThreadListWriter::MinidumpThreadListWriter()
: MinidumpStreamWriter(),
thread_list_base_(),
threads_(),
memory_list_writer_(nullptr) {
memory_list_writer_(nullptr),
thread_list_base_() {
}
MinidumpThreadListWriter::~MinidumpThreadListWriter() {

View File

@ -202,9 +202,9 @@ class MinidumpThreadListWriter final : public internal::MinidumpStreamWriter {
MinidumpStreamType StreamType() const override;
private:
MINIDUMP_THREAD_LIST thread_list_base_;
PointerVector<MinidumpThreadWriter> threads_;
MinidumpMemoryListWriter* memory_list_writer_; // weak
MINIDUMP_THREAD_LIST thread_list_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpThreadListWriter);
};