Skip to content

Commit 45e6861

Browse files
committed
Require unique_ptr to Module::addFunctionType()
This fixes the memory leak in WasmBinaryBuilder::readSignatures() caused probably the exception thrown there before the FunctionType object is safe. This also makes it clear that the Module becomes the owner of the FunctionType objects.
1 parent f831369 commit 45e6861

File tree

9 files changed

+32
-30
lines changed

9 files changed

+32
-30
lines changed

src/asmjs/asm_v_wasm.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,13 @@ FunctionType* ensureFunctionType(std::string sig, Module* wasm) {
9999
return wasm->getFunctionType(name);
100100
}
101101
// add new type
102-
auto type = new FunctionType;
102+
std::unique_ptr<FunctionType> type{new FunctionType};
103103
type->name = name;
104104
type->result = sigToType(sig[0]);
105105
for (size_t i = 1; i < sig.size(); i++) {
106106
type->params.push_back(sigToType(sig[i]));
107107
}
108-
wasm->addFunctionType(type);
109-
return type;
108+
return wasm->addFunctionType(std::move(type));
110109
}
111110

112111
Expression* ensureDouble(Expression* expr, MixedArena& allocator) {

src/binaryen-c.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -190,41 +190,42 @@ void BinaryenModuleDispose(BinaryenModuleRef module) {
190190

191191
// Function types
192192

193-
BinaryenFunctionTypeRef BinaryenAddFunctionType(BinaryenModuleRef module, const char* name, BinaryenType result, BinaryenType* paramTypes, BinaryenIndex numParams) {
193+
BinaryenFunctionTypeRef BinaryenAddFunctionType(BinaryenModuleRef module, const char* name,
194+
BinaryenType result, BinaryenType* paramTypes, BinaryenIndex numParams) {
194195
auto* wasm = (Module*)module;
195-
auto* ret = new FunctionType;
196-
if (name) ret->name = name;
197-
else ret->name = Name::fromInt(wasm->functionTypes.size());
196+
std::unique_ptr<FunctionType> ret{new FunctionType};
197+
if (name)
198+
ret->name = name;
199+
else
200+
ret->name = Name::fromInt(wasm->functionTypes.size());
198201
ret->result = Type(result);
199202
for (BinaryenIndex i = 0; i < numParams; i++) {
200203
ret->params.push_back(Type(paramTypes[i]));
201204
}
202205

203-
// Lock. This can be called from multiple threads at once, and is a
204-
// point where they all access and modify the module.
205-
{
206-
std::lock_guard<std::mutex> lock(BinaryenFunctionTypeMutex);
207-
wasm->addFunctionType(ret);
208-
}
209-
210206
if (tracing) {
211207
std::cout << " {\n";
212208
std::cout << " BinaryenType paramTypes[] = { ";
213209
for (BinaryenIndex i = 0; i < numParams; i++) {
214-
if (i > 0) std::cout << ", ";
210+
if (i > 0)
211+
std::cout << ", ";
215212
std::cout << paramTypes[i];
216213
}
217-
if (numParams == 0) std::cout << "0"; // ensure the array is not empty, otherwise a compiler error on VS
214+
if (numParams == 0)
215+
std::cout << "0"; // ensure the array is not empty, otherwise a compiler error on VS
218216
std::cout << " };\n";
219217
size_t id = functionTypes.size();
220218
std::cout << " functionTypes[" << id << "] = BinaryenAddFunctionType(the_module, ";
221-
functionTypes[ret] = id;
219+
functionTypes[ret.get()] = id;
222220
traceNameOrNULL(name);
223221
std::cout << ", " << result << ", paramTypes, " << numParams << ");\n";
224222
std::cout << " }\n";
225223
}
226224

227-
return ret;
225+
// Lock. This can be called from multiple threads at once, and is a
226+
// point where they all access and modify the module.
227+
std::lock_guard<std::mutex> lock(BinaryenFunctionTypeMutex);
228+
return wasm->addFunctionType(std::move(ret));
228229
}
229230
void BinaryenRemoveFunctionType(BinaryenModuleRef module, const char* name) {
230231
if (tracing) {

src/ir/module-utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ inline void copyModule(Module& in, Module& out) {
7373
// we use names throughout, not raw points, so simple copying is fine
7474
// for everything *but* expressions
7575
for (auto& curr : in.functionTypes) {
76-
out.addFunctionType(new FunctionType(*curr));
76+
out.addFunctionType(std::unique_ptr<FunctionType>{new FunctionType(*curr)});
7777
}
7878
for (auto& curr : in.imports) {
7979
out.addImport(new Import(*curr));

src/passes/LegalizeJSInterface.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ struct LegalizeJSInterface : public Pass {
181181
// wasm calls the import, so it must call a stub that calls the actual legal JS import
182182
Import* makeLegalStub(Import* im, Module* module, Name& funcName) {
183183
Builder builder(*module);
184-
auto* type = new FunctionType();
184+
std::unique_ptr<FunctionType> type{new FunctionType()};
185185
type->name = Name(std::string("legaltype$") + im->name.str);
186186
auto* legal = new Import();
187187
legal->name = Name(std::string("legalimport$") + im->name.str);
@@ -233,7 +233,7 @@ struct LegalizeJSInterface : public Pass {
233233
func->result = imFunctionType->result;
234234

235235
module->addFunction(func);
236-
module->addFunctionType(type);
236+
module->addFunctionType(std::move(type));
237237
return legal;
238238
}
239239

src/tools/wasm-merge.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ struct InputMergeable : public ExpressionStackWalker<InputMergeable, Visitor<Inp
446446

447447
// copy in the data
448448
for (auto& curr : wasm.functionTypes) {
449-
outputMergeable.wasm.addFunctionType(curr.release());
449+
outputMergeable.wasm.addFunctionType(std::move(curr));
450450
}
451451
for (auto& curr : wasm.imports) {
452452
if (curr->kind == ExternalKind::Memory || curr->kind == ExternalKind::Table) {

src/wasm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ class Module {
786786
Function* getFunctionOrNull(Name name);
787787
Global* getGlobalOrNull(Name name);
788788

789-
void addFunctionType(FunctionType* curr);
789+
FunctionType* addFunctionType(std::unique_ptr<FunctionType> curr);
790790
void addImport(Import* curr);
791791
void addExport(Export* curr);
792792
void addFunction(Function* curr);

src/wasm/wasm-binary.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ void WasmBinaryBuilder::readSignatures() {
909909
if (debug) std::cerr << "num: " << numTypes << std::endl;
910910
for (size_t i = 0; i < numTypes; i++) {
911911
if (debug) std::cerr << "read one" << std::endl;
912-
auto curr = new FunctionType;
912+
std::unique_ptr<FunctionType> curr{new FunctionType};
913913
auto form = getS32LEB();
914914
if (form != BinaryConsts::EncodedType::Func) {
915915
throwError("bad signature form " + std::to_string(form));
@@ -929,7 +929,7 @@ void WasmBinaryBuilder::readSignatures() {
929929
curr->result = getType();
930930
}
931931
curr->name = Name::fromInt(wasm.functionTypes.size());
932-
wasm.addFunctionType(curr);
932+
wasm.addFunctionType(std::move(curr));
933933
}
934934
}
935935

src/wasm/wasm-s-parser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
419419
functionType->name = Name::fromInt(wasm.functionTypes.size());
420420
functionTypeNames.push_back(functionType->name);
421421
if (wasm.getFunctionTypeOrNull(functionType->name)) throw ParseException("duplicate function type", s.line, s.col);
422-
wasm.addFunctionType(functionType.release());
422+
wasm.addFunctionType(std::move(functionType));
423423
}
424424
}
425425
}
@@ -1965,7 +1965,7 @@ void SExpressionWasmBuilder::parseType(Element& s) {
19651965
}
19661966
functionTypeNames.push_back(type->name);
19671967
if (wasm.getFunctionTypeOrNull(type->name)) throw ParseException("duplicate function type", s.line, s.col);
1968-
wasm.addFunctionType(type.release());
1968+
wasm.addFunctionType(std::move(type));
19691969
}
19701970

19711971
} // namespace wasm

src/wasm/wasm.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -722,15 +722,17 @@ Global* Module::getGlobalOrNull(Name name) {
722722
return iter->second;
723723
}
724724

725-
void Module::addFunctionType(FunctionType* curr) {
725+
FunctionType* Module::addFunctionType(std::unique_ptr<FunctionType> curr) {
726726
if (!curr->name.is()) {
727727
Fatal() << "Module::addFunctionType: empty name";
728728
}
729729
if (getFunctionTypeOrNull(curr->name)) {
730730
Fatal() << "Module::addFunctionType: " << curr->name << " already exists";
731731
}
732-
functionTypes.push_back(std::unique_ptr<FunctionType>(curr));
733-
functionTypesMap[curr->name] = curr;
732+
auto p = curr.get();
733+
functionTypes.emplace_back(std::move(curr));
734+
functionTypesMap[curr->name] = p;
735+
return p;
734736
}
735737

736738
void Module::addImport(Import* curr) {

0 commit comments

Comments
 (0)