Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions sandboxed_api/tools/clang_generator/emitter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,10 @@ absl::StatusOr<std::string> Emitter::DoEmitFunction(

absl::StrAppend(&out, ") {\n");

// Declare the return value of the SAPI function.
absl::StrAppend(&out, type_mapper.MapQualType(return_type), " v_ret_;\n");
// Declare the return value of the SAPI function. The variable is not
// suffixed with an underscore like the parameter variables below, so that a
// parameter named `ret` cannot collide with it.
absl::StrAppend(&out, type_mapper.MapQualType(return_type), " v_ret;\n");

// Declare the local variables for the parameters.
for (const auto& [qual, name] : params) {
Expand All @@ -460,15 +462,15 @@ absl::StatusOr<std::string> Emitter::DoEmitFunction(

// Call the sandboxed function.
absl::StrAppend(&out, "\nABSL_RETURN_IF_ERROR(sandbox_->Call(\"",
function_name, "\", &v_ret_");
function_name, "\", &v_ret");
for (const auto& [qual, name] : params) {
absl::StrAppend(&out, ", ", IsPointerOrReference(qual) ? "" : "&v_", name);
}

// End the sandboxed function call and return `ok` if the unsandboxed function
// returns void, or else return the value of the SAPI function.
absl::StrAppend(&out, "));\nreturn ",
(returns_void ? "::absl::OkStatus()" : "v_ret_.GetValue()"),
(returns_void ? "::absl::OkStatus()" : "v_ret.GetValue()"),
";\n}\n");
return out;
}
Expand Down
21 changes: 21 additions & 0 deletions sandboxed_api/tools/clang_generator/emitter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,27 @@ TEST_F(EmitterTest, AllFunctionsLimitScanDepthFailure) {
EXPECT_THAT(emitter.GetRenderedFunctions(), IsEmpty());
}

// Tests that the generator produces valid code for functions that have a
// parameter named `ret`. The local copy of the parameter and the return value
// variable must not collide (both would be named `v_ret_`).
TEST_F(EmitterTest, ParameterNamedRet) {
GeneratorOptions options;
EmitterForTesting emitter(&options);
ASSERT_THAT(RunFrontendAction(
R"(extern "C" int FunctionWithRet(int ret);)",
std::make_unique<GeneratorAction>(&emitter, &options)),
IsOk());
EXPECT_THAT(emitter.GetRenderedFunctions(), SizeIs(1));

absl::StatusOr<std::string> header = emitter.EmitHeader();
ASSERT_THAT(header, IsOk());
const std::string uglified = UglifyAll({*header})[0];

// The return value slot and the parameter copy must be passed to
// sandbox_->Call() as two distinct variables.
EXPECT_THAT(uglified, HasSubstr("&v_ret, &v_ret_"));
}

TEST_F(EmitterTest, RelatedTypes) {
GeneratorOptions options;
EmitterForTesting emitter(&options);
Expand Down