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 "minidump/minidump_simple_string_dictionary_writer.h"
16 
17 #include <utility>
18 
19 #include "base/logging.h"
20 #include "util/file/file_writer.h"
21 #include "util/numeric/safe_assignment.h"
22 
23 namespace crashpad {
24 
25 MinidumpSimpleStringDictionaryEntryWriter::
MinidumpSimpleStringDictionaryEntryWriter()26     MinidumpSimpleStringDictionaryEntryWriter()
27     : MinidumpWritable(), entry_(), key_(), value_() {
28 }
29 
30 MinidumpSimpleStringDictionaryEntryWriter::
~MinidumpSimpleStringDictionaryEntryWriter()31     ~MinidumpSimpleStringDictionaryEntryWriter() {
32 }
33 
34 const MinidumpSimpleStringDictionaryEntry*
35 MinidumpSimpleStringDictionaryEntryWriter::
GetMinidumpSimpleStringDictionaryEntry() const36     GetMinidumpSimpleStringDictionaryEntry() const {
37   DCHECK_EQ(state(), kStateWritable);
38 
39   return &entry_;
40 }
41 
SetKeyValue(const std::string & key,const std::string & value)42 void MinidumpSimpleStringDictionaryEntryWriter::SetKeyValue(
43     const std::string& key,
44     const std::string& value) {
45   DCHECK_EQ(state(), kStateMutable);
46 
47   key_.SetUTF8(key);
48   value_.SetUTF8(value);
49 }
50 
Freeze()51 bool MinidumpSimpleStringDictionaryEntryWriter::Freeze() {
52   DCHECK_EQ(state(), kStateMutable);
53 
54   if (!MinidumpWritable::Freeze()) {
55     return false;
56   }
57 
58   key_.RegisterRVA(&entry_.key);
59   value_.RegisterRVA(&entry_.value);
60 
61   return true;
62 }
63 
SizeOfObject()64 size_t MinidumpSimpleStringDictionaryEntryWriter::SizeOfObject() {
65   DCHECK_GE(state(), kStateFrozen);
66 
67   // This object doesn’t directly write anything itself. Its
68   // MinidumpSimpleStringDictionaryEntry is written by its parent as part of a
69   // MinidumpSimpleStringDictionary, and its children are responsible for
70   // writing themselves.
71   return 0;
72 }
73 
74 std::vector<internal::MinidumpWritable*>
Children()75 MinidumpSimpleStringDictionaryEntryWriter::Children() {
76   DCHECK_GE(state(), kStateFrozen);
77 
78   std::vector<MinidumpWritable*> children(1, &key_);
79   children.push_back(&value_);
80   return children;
81 }
82 
WriteObject(FileWriterInterface * file_writer)83 bool MinidumpSimpleStringDictionaryEntryWriter::WriteObject(
84     FileWriterInterface* file_writer) {
85   DCHECK_EQ(state(), kStateWritable);
86 
87   // This object doesn’t directly write anything itself. Its
88   // MinidumpSimpleStringDictionaryEntry is written by its parent as part of a
89   // MinidumpSimpleStringDictionary, and its children are responsible for
90   // writing themselves.
91   return true;
92 }
93 
MinidumpSimpleStringDictionaryWriter()94 MinidumpSimpleStringDictionaryWriter::MinidumpSimpleStringDictionaryWriter()
95     : MinidumpWritable(),
96       entries_(),
97       simple_string_dictionary_base_(new MinidumpSimpleStringDictionary()) {
98 }
99 
~MinidumpSimpleStringDictionaryWriter()100 MinidumpSimpleStringDictionaryWriter::~MinidumpSimpleStringDictionaryWriter() {
101   for (auto& item : entries_)
102     delete item.second;
103 }
104 
InitializeFromMap(const std::map<std::string,std::string> & map)105 void MinidumpSimpleStringDictionaryWriter::InitializeFromMap(
106     const std::map<std::string, std::string>& map) {
107   DCHECK_EQ(state(), kStateMutable);
108   DCHECK(entries_.empty());
109 
110   for (const auto& iterator : map) {
111     auto entry = std::make_unique<MinidumpSimpleStringDictionaryEntryWriter>();
112     entry->SetKeyValue(iterator.first, iterator.second);
113     AddEntry(std::move(entry));
114   }
115 }
116 
AddEntry(std::unique_ptr<MinidumpSimpleStringDictionaryEntryWriter> entry)117 void MinidumpSimpleStringDictionaryWriter::AddEntry(
118     std::unique_ptr<MinidumpSimpleStringDictionaryEntryWriter> entry) {
119   DCHECK_EQ(state(), kStateMutable);
120 
121   const std::string& key = entry->Key();
122   auto iterator = entries_.find(key);
123   if (iterator != entries_.end()) {
124     delete iterator->second;
125     iterator->second = entry.release();
126   } else {
127     entries_[key] = entry.release();
128   }
129 }
130 
IsUseful() const131 bool MinidumpSimpleStringDictionaryWriter::IsUseful() const {
132   return !entries_.empty();
133 }
134 
Freeze()135 bool MinidumpSimpleStringDictionaryWriter::Freeze() {
136   DCHECK_EQ(state(), kStateMutable);
137 
138   if (!MinidumpWritable::Freeze()) {
139     return false;
140   }
141 
142   size_t entry_count = entries_.size();
143   if (!AssignIfInRange(&simple_string_dictionary_base_->count, entry_count)) {
144     LOG(ERROR) << "entry_count " << entry_count << " out of range";
145     return false;
146   }
147 
148   return true;
149 }
150 
SizeOfObject()151 size_t MinidumpSimpleStringDictionaryWriter::SizeOfObject() {
152   DCHECK_GE(state(), kStateFrozen);
153 
154   return sizeof(*simple_string_dictionary_base_) +
155          entries_.size() * sizeof(MinidumpSimpleStringDictionaryEntry);
156 }
157 
158 std::vector<internal::MinidumpWritable*>
Children()159 MinidumpSimpleStringDictionaryWriter::Children() {
160   DCHECK_GE(state(), kStateMutable);
161 
162   std::vector<MinidumpWritable*> children;
163   for (const auto& key_entry : entries_) {
164     children.push_back(key_entry.second);
165   }
166 
167   return children;
168 }
169 
WriteObject(FileWriterInterface * file_writer)170 bool MinidumpSimpleStringDictionaryWriter::WriteObject(
171     FileWriterInterface* file_writer) {
172   DCHECK_GE(state(), kStateWritable);
173 
174   WritableIoVec iov;
175   iov.iov_base = simple_string_dictionary_base_.get();
176   iov.iov_len = sizeof(*simple_string_dictionary_base_);
177   std::vector<WritableIoVec> iovecs(1, iov);
178 
179   for (const auto& key_entry : entries_) {
180     iov.iov_base = key_entry.second->GetMinidumpSimpleStringDictionaryEntry();
181     iov.iov_len = sizeof(MinidumpSimpleStringDictionaryEntry);
182     iovecs.push_back(iov);
183   }
184 
185   return file_writer->WriteIoVec(&iovecs);
186 }
187 
188 }  // namespace crashpad
189