Fix dangling pointer in forward_ref_die_to_func

Bug: google-breakpad:843
Change-Id: I14358b239604e1faeb5a8c4c4734102571dbed09
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/2951787
Reviewed-by: Mike Frysinger <vapier@chromium.org>
This commit is contained in:
Zequan Wu 2021-06-10 11:09:24 -07:00 committed by Mike Frysinger
parent 322eb2b4c6
commit a524a1e24b
5 changed files with 26 additions and 22 deletions

View file

@ -269,6 +269,9 @@ struct DwarfCUToModule::CUContext {
//
// Destroying this destroys all the functions this vector points to.
vector<Module::Function*> functions;
// A map of function pointers to the its forward specification DIE's offset.
map<Module::Function*, uint64_t> spec_function_offsets;
};
// Information about the context of a particular DIE. This is for
@ -714,6 +717,9 @@ void DwarfCUToModule::FuncHandler::Finish() {
cu_context_->file_context->file_private_
->forward_ref_die_to_func[forward_ref_die_offset_] =
cu_context_->functions.back();
cu_context_->spec_function_offsets[cu_context_->functions.back()] =
forward_ref_die_offset_;
}
}
} else if (inline_) {
@ -1313,9 +1319,15 @@ void DwarfCUToModule::Finish() {
AssignLinesToFunctions();
// Add our functions, which now have source lines assigned to them,
// to module_.
cu_context_->file_context->module_->AddFunctions(functions->begin(),
functions->end());
// to module_, and remove duplicate functions.
for (Module::Function* func : *functions)
if (!cu_context_->file_context->module_->AddFunction(func)) {
auto iter = cu_context_->spec_function_offsets.find(func);
if (iter != cu_context_->spec_function_offsets.end())
cu_context_->file_context->file_private_->forward_ref_die_to_func.erase(
iter->second);
delete func;
}
// Ownership of the function objects has shifted from cu_context to
// the Module.

View file

@ -80,13 +80,13 @@ void Module::SetAddressRanges(const vector<Range>& ranges) {
address_ranges_ = ranges;
}
void Module::AddFunction(Function* function) {
bool Module::AddFunction(Function* function) {
// FUNC lines must not hold an empty name, so catch the problem early if
// callers try to add one.
assert(!function->name.empty());
if (!AddressIsInModule(function->address)) {
return;
return false;
}
// FUNCs are better than PUBLICs as they come with sizes, so remove an extern
@ -120,14 +120,9 @@ void Module::AddFunction(Function* function) {
if (!ret.second && (*ret.first != function)) {
// Free the duplicate that was not inserted because this Module
// now owns it.
delete function;
return false;
}
}
void Module::AddFunctions(vector<Function*>::iterator begin,
vector<Function*>::iterator end) {
for (vector<Function*>::iterator it = begin; it != end; ++it)
AddFunction(*it);
return true;
}
void Module::AddStackFrameEntry(StackFrameEntry* stack_frame_entry) {

View file

@ -216,13 +216,8 @@ class Module {
// Add FUNCTION to the module. FUNCTION's name must not be empty.
// This module owns all Function objects added with this function:
// destroying the module destroys them as well.
void AddFunction(Function* function);
// Add all the functions in [BEGIN,END) to the module.
// This module owns all Function objects added with this function:
// destroying the module destroys them as well.
void AddFunctions(vector<Function*>::iterator begin,
vector<Function*>::iterator end);
// Return false if the function is duplicate and needs to be freed.
bool AddFunction(Function* function);
// Add STACK_FRAME_ENTRY to the module.
// This module owns all StackFrameEntry objects added with this

View file

@ -265,7 +265,7 @@ TEST(Write, NoCFI) {
contents.c_str());
}
TEST(Construct, AddFunctions) {
TEST(Construct, AddFunction) {
stringstream s;
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
@ -287,7 +287,8 @@ TEST(Construct, AddFunctions) {
vec.push_back(function1);
vec.push_back(function2);
m.AddFunctions(vec.begin(), vec.end());
for (Module::Function* func: vec)
m.AddFunction(func);
m.Write(s, ALL_SYMBOL_DATA);
string contents = s.str();

View file

@ -192,7 +192,8 @@ void StabsToModule::Finalize() {
}
// Now that everything has a size, add our functions to the module, and
// dispose of our private list.
module_->AddFunctions(functions_.begin(), functions_.end());
for (Module::Function* func: functions_)
module_->AddFunction(func);
functions_.clear();
}