Skip to content

Commit 700d5b8

Browse files
committed
review: stop copying source
Signed-off-by: Takeshi Yoneda <[email protected]>
1 parent 57bb777 commit 700d5b8

File tree

5 files changed

+63
-93
lines changed

5 files changed

+63
-93
lines changed

src/common/wasm_util.cc

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,21 @@
1313
// limitations under the License.
1414

1515
#include "src/common/wasm_util.h"
16-
#include <cstdio>
17-
#include <string.h>
16+
#include <cstring>
1817

1918
namespace proxy_wasm {
2019
namespace common {
2120

22-
bool WasmUtil::getCustomSection(const char *begin, const char *end, std::string_view name,
21+
bool WasmUtil::checkWasmHeader(std::string_view bytecode) {
22+
static const uint8_t wasm_magic_number[4] = {0x00, 0x61, 0x73, 0x6d};
23+
return bytecode.size() < 8 || !::memcmp(bytecode.data(), wasm_magic_number, 4);
24+
}
25+
26+
bool WasmUtil::getCustomSection(std::string_view bytecode, std::string_view name,
2327
std::string_view &ret) {
2428
// Skip the Wasm header.
25-
const char *pos = begin + 8;
29+
const char *pos = bytecode.data() + 8;
30+
const char *end = bytecode.data() + bytecode.size();
2631
while (pos < end) {
2732
if (pos + 1 > end) {
2833
return false;
@@ -53,10 +58,10 @@ bool WasmUtil::getCustomSection(const char *begin, const char *end, std::string_
5358
return true;
5459
};
5560

56-
bool WasmUtil::getFunctionNameIndex(const char *begin, const char *end,
61+
bool WasmUtil::getFunctionNameIndex(std::string_view bytecode,
5762
std::unordered_map<uint32_t, std::string> &ret) {
5863
std::string_view name_section = {};
59-
if (!WasmUtil::getCustomSection(begin, end, "name", name_section)) {
64+
if (!WasmUtil::getCustomSection(bytecode, "name", name_section)) {
6065
return false;
6166
};
6267
if (!name_section.empty()) {
@@ -101,9 +106,10 @@ bool WasmUtil::getFunctionNameIndex(const char *begin, const char *end,
101106
return true;
102107
}
103108

104-
bool WasmUtil::getStrippedSource(const char *begin, const char *end, std::vector<char> &ret) {
109+
bool WasmUtil::getStrippedSource(std::string_view bytecode, std::string &ret) {
105110
// Skip the Wasm header.
106-
const char *pos = begin + 8;
111+
const char *pos = bytecode.data() + 8;
112+
const char *end = bytecode.data() + bytecode.size();
107113
while (pos < end) {
108114
const auto section_start = pos;
109115
if (pos + 1 > end) {
@@ -125,7 +131,7 @@ bool WasmUtil::getStrippedSource(const char *begin, const char *end, std::vector
125131
// If this is the first "precompiled_" section, then save everything
126132
// before it, otherwise skip it.
127133
if (ret.empty()) {
128-
const char *start = begin;
134+
const char *start = bytecode.data();
129135
ret.insert(ret.end(), start, section_start);
130136
}
131137
}

src/common/wasm_util.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace common {
2323
// Utilitiy functions which directly operate on Wasm bytecodes.
2424
class WasmUtil {
2525
public:
26+
static bool checkWasmHeader(std::string_view bytecode);
2627
/**
2728
* getCustomSection extract the view of the custom section for a given name.
2829
* @param begin is the beggining of bytecode.
@@ -31,7 +32,7 @@ class WasmUtil {
3132
* @param ret is the reference to store the resulting view to the custom section.
3233
* @return indicates whether parsing succeeded or not.
3334
*/
34-
static bool getCustomSection(const char *begin, const char *end, std::string_view name,
35+
static bool getCustomSection(std::string_view bytecode, std::string_view name,
3536
std::string_view &ret);
3637

3738
/**
@@ -43,7 +44,7 @@ class WasmUtil {
4344
* @param ret the reference to store map from function indexes to function names.
4445
* @return indicates whether parsing succeeded or not.
4546
*/
46-
static bool getFunctionNameIndex(const char *begin, const char *end,
47+
static bool getFunctionNameIndex(std::string_view bytecode,
4748
std::unordered_map<uint32_t, std::string> &ret);
4849

4950
/**
@@ -53,15 +54,9 @@ class WasmUtil {
5354
* @param ret the reference to the stripped bytecode.
5455
* @return indicates whether parsing succeeded or not.
5556
*/
56-
static bool getStrippedSource(const char *begin, const char *end, std::vector<char> &ret);
57+
static bool getStrippedSource(std::string_view bytecode, std::string &ret);
5758

58-
/**
59-
* parseVarint parses the bytecode following LEB128.
60-
* @param begin is the postion where parsing starts.
61-
* @param end is the end of bytecode.
62-
* @param ret is the reference to store the resulting value.
63-
* @return indicates whether parsing succeeded or not.
64-
*/
59+
private:
6560
static bool parseVarint(const char *&begin, const char *end, uint32_t &ret);
6661
};
6762

src/v8/v8.cc

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ class V8 : public WasmVm {
113113
void getModuleFunctionImpl(std::string_view function_name,
114114
std::function<R(ContextBase *, Args...)> *function);
115115

116-
wasm::vec<byte_t> source_ = wasm::vec<byte_t>::invalid();
117116
wasm::own<wasm::Store> store_;
118117
wasm::own<wasm::Module> module_;
119118
wasm::own<wasm::Shared<wasm::Module>> shared_module_;
@@ -255,22 +254,15 @@ bool V8::load(const std::string &code, bool allow_precompiled) {
255254
store_ = wasm::Store::make(engine());
256255

257256
// Wasm file header is 8 bytes (magic number + version).
258-
static const uint8_t magic_number[4] = {0x00, 0x61, 0x73, 0x6d};
259-
if (code.size() < 8 || ::memcmp(code.data(), magic_number, 4) != 0) {
257+
if (!common::WasmUtil::checkWasmHeader(code)) {
260258
return false;
261259
}
262260

263-
source_ = wasm::vec<byte_t>::make_uninitialized(code.size());
264-
::memcpy(source_.get(), code.data(), code.size());
265-
266-
const char *source_begin = source_.get();
267-
const char *source_end = source_begin + source_.size();
268261
if (allow_precompiled) {
269262
const auto section_name = getPrecompiledSectionName();
270263
if (!section_name.empty()) {
271-
string_view precompiled = {};
272-
if (!common::WasmUtil::getCustomSection(source_begin, source_end, section_name,
273-
precompiled)) {
264+
std::string_view precompiled = {};
265+
if (!common::WasmUtil::getCustomSection(code, section_name, precompiled)) {
274266
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
275267
return false;
276268
}
@@ -289,19 +281,28 @@ bool V8::load(const std::string &code, bool allow_precompiled) {
289281
}
290282

291283
if (!module_) {
292-
const std::vector<char> stripped =
293-
common::WasmUtil::getStrippedSource(source_begin, source_end);
294-
module_ = wasm::Module::make(
295-
store_.get(),
296-
stripped.empty() ? source_ : wasm::vec<byte_t>::make(stripped.size(), stripped.data()));
284+
std::string stripped;
285+
if (!common::WasmUtil::getStrippedSource(code, stripped)) {
286+
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
287+
return false;
288+
};
289+
wasm::vec<byte_t> code_vec = wasm::vec<byte_t>::invalid();
290+
if (stripped.empty()) {
291+
// Use the original bytecode.
292+
code_vec = wasm::vec<byte_t>::make(code.size(), (char *)(code.data()));
293+
} else {
294+
// Othewise use the stripped bytecode.
295+
code_vec = wasm::vec<byte_t>::make(stripped.size(), stripped.data());
296+
}
297+
module_ = wasm::Module::make(store_.get(), code_vec);
297298
}
298299

299300
if (module_) {
300301
shared_module_ = module_->share();
301302
assert((shared_module_ != nullptr));
302303
}
303304

304-
if (!common::WasmUtil::getFunctionNameIndex(source_begin, source_end, function_names_index_)) {
305+
if (!common::WasmUtil::getFunctionNameIndex(code, function_names_index_)) {
305306
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
306307
};
307308
return module_ != nullptr;

src/wasmtime/wasmtime.cc

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ class Wasmtime : public WasmVm {
9999
void getModuleFunctionImpl(std::string_view function_name,
100100
std::function<R(ContextBase *, Args...)> *function);
101101

102-
WasmByteVec source_;
103102
WasmStorePtr store_;
104103
WasmModulePtr module_;
105104
WasmSharedModulePtr shared_module_;
@@ -115,29 +114,25 @@ class Wasmtime : public WasmVm {
115114
bool Wasmtime::load(const std::string &code, bool allow_precompiled) {
116115
store_ = wasm_store_new(engine());
117116

118-
// Wasm file header is 8 bytes (magic number + version).
119-
static const uint8_t magic_number[4] = {0x00, 0x61, 0x73, 0x6d};
120-
if (code.size() < 8 || ::memcmp(code.data(), magic_number, 4) != 0) {
117+
if (!common::WasmUtil::checkWasmHeader(code)) {
121118
return false;
122119
}
123120

124-
wasm_byte_vec_new_uninitialized(source_.get(), code.size());
125-
::memcpy(source_.get()->data, code.data(), code.size());
126-
127-
std::vector<char> stripped_vec;
128-
if (!common::WasmUtil::getStrippedSource(
129-
source_.get()->data, source_.get()->data + source_.get()->size, stripped_vec)) {
121+
std::vector<uint8_t> stripped_vec;
122+
if (!common::WasmUtil::getStrippedSource(code, stripped_vec)) {
130123
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
124+
return false;
131125
};
132126

133127
if (stripped_vec.empty()) {
134-
// Use the original source.
135-
module_ = wasm_module_new(store_.get(), source_.get());
128+
// Use the original bytecode.
129+
WasmByteVec source_vec;
130+
wasm_byte_vec_new(source_vec.get(), code.size(), code.data());
131+
module_ = wasm_module_new(store_.get(), source_vec.get());
136132
} else {
137133
// Othewise pass the stripped source code.
138134
WasmByteVec stripped;
139-
wasm_byte_vec_new_uninitialized(stripped.get(), stripped_vec.size());
140-
::memcpy(stripped.get()->data, stripped_vec.data(), stripped_vec.size());
135+
wasm_byte_vec_new(stripped.get(), code.size(), code.data());
141136
module_ = wasm_module_new(store_.get(), stripped.get());
142137
}
143138

test/common/wasm_util_test.cc

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace proxy_wasm {
2626
namespace common {
2727

2828
TEST(TestWasmCommonUtil, getCustomSection) {
29-
std::vector<char> custom_section = {
29+
std::string custom_section = {
3030
0x00, 0x61, 0x73, 0x6d, // Wasm magic
3131
0x01, 0x00, 0x00, 0x00, // Wasm version
3232
0x00, // custom section id
@@ -37,48 +37,47 @@ TEST(TestWasmCommonUtil, getCustomSection) {
3737
std::string_view section = {};
3838

3939
// OK.
40-
EXPECT_TRUE(WasmUtil::getCustomSection(
41-
custom_section.data(), custom_section.data() + custom_section.size(), "hey!", section));
40+
EXPECT_TRUE(WasmUtil::getCustomSection(custom_section, "hey!", section));
4241
EXPECT_EQ(std::string(section), "hello");
4342
section = {};
4443

4544
// Non exist.
46-
EXPECT_TRUE(WasmUtil::getCustomSection(
47-
custom_section.data(), custom_section.data() + custom_section.size(), "non-exist", section));
45+
EXPECT_TRUE(WasmUtil::getCustomSection(custom_section, "non-exist", section));
4846
EXPECT_EQ(section, "");
4947

5048
// Fail due to the corrupted bytecode.
5149
// TODO(@mathetake): here we haven't covered all the parsing failure branches. Add more cases.
52-
EXPECT_FALSE(WasmUtil::getCustomSection(
53-
custom_section.data(), custom_section.data() + custom_section.size() - 3, "hey", section));
54-
EXPECT_FALSE(WasmUtil::getCustomSection(
55-
custom_section.data() + 1, custom_section.data() + custom_section.size(), "hey", section));
50+
std::string corrupted = {custom_section.data(),
51+
custom_section.data() + custom_section.size() - 3};
52+
EXPECT_FALSE(WasmUtil::getCustomSection(corrupted, "hey", section));
53+
corrupted = {custom_section.data() + 1, custom_section.data() + custom_section.size()};
54+
EXPECT_FALSE(WasmUtil::getCustomSection(corrupted, "hey", section));
5655
}
5756

5857
TEST(TestWasmCommonUtil, getFunctionNameIndex) {
5958
const auto source = readTestWasmFile("abi_export.wasm");
6059
std::unordered_map<uint32_t, std::string> actual;
6160
// OK.
62-
EXPECT_TRUE(WasmUtil::getFunctionNameIndex(source.data(), source.data() + source.size(), actual));
61+
EXPECT_TRUE(WasmUtil::getFunctionNameIndex(source, actual));
6362
EXPECT_FALSE(actual.empty());
6463
EXPECT_EQ(actual.find(0)->second, "proxy_abi_version_0_2_0");
6564

6665
// Fail due to the corrupted bytecode.
6766
// TODO(@mathetake): here we haven't covered all the parsing failure branches. Add more cases.
6867
actual = {};
6968
std::string_view name_section = {};
70-
EXPECT_TRUE(WasmUtil::getCustomSection(source.data(), source.data() + source.size(), "name",
71-
name_section));
69+
EXPECT_TRUE(WasmUtil::getCustomSection(source, "name", name_section));
7270
// Passing module with malformed custom section.
73-
EXPECT_FALSE(WasmUtil::getFunctionNameIndex(source.data(), name_section.data() + 1, actual));
71+
std::string corrupted = {source.data(), name_section.data() + 1};
72+
EXPECT_FALSE(WasmUtil::getFunctionNameIndex(corrupted, actual));
7473
EXPECT_TRUE(actual.empty());
7574
}
7675

7776
TEST(TestWasmCommonUtil, getStrippedSource) {
7877
// Unmodified case.
7978
auto source = readTestWasmFile("abi_export.wasm");
80-
std::vector<char> actual;
81-
EXPECT_TRUE(WasmUtil::getStrippedSource(source.data(), source.data() + source.size(), actual));
79+
std::vector<uint8_t> actual;
80+
EXPECT_TRUE(WasmUtil::getStrippedSource(source, actual));
8281
// No `precompiled_` is found in the custom sections.
8382
EXPECT_TRUE(actual.empty());
8483

@@ -97,42 +96,16 @@ TEST(TestWasmCommonUtil, getStrippedSource) {
9796

9897
source.append(custom_section.data(), custom_section.size());
9998
std::string_view section = {};
100-
EXPECT_TRUE(WasmUtil::getCustomSection(source.data(), source.data() + source.size(),
101-
"precompiled_test", section));
99+
EXPECT_TRUE(WasmUtil::getCustomSection(source, "precompiled_test", section));
102100
EXPECT_FALSE(section.empty());
103101

104102
// Chcek if the custom section is stripped.
105103
actual = {};
106-
EXPECT_TRUE(WasmUtil::getStrippedSource(source.data(), source.data() + source.size(), actual));
104+
EXPECT_TRUE(WasmUtil::getStrippedSource(source, actual));
107105
// No `precompiled_` is found in the custom sections.
108106
EXPECT_FALSE(actual.empty());
109107
EXPECT_EQ(actual.size(), source.size() - custom_section.size());
110108
}
111109

112-
TEST(WasmUtil, parseVarint) {
113-
std::vector<char> source;
114-
const char *begin = source.data();
115-
uint32_t ret = 0;
116-
EXPECT_FALSE(WasmUtil::parseVarint(begin, source.data(), ret));
117-
118-
source = {0x04};
119-
begin = source.data();
120-
EXPECT_TRUE(WasmUtil::parseVarint(begin, begin + source.size(), ret));
121-
EXPECT_EQ(0x04, ret);
122-
ret = 0;
123-
124-
source = {static_cast<char>(0x80), 0x7f};
125-
begin = source.data();
126-
EXPECT_TRUE(WasmUtil::parseVarint(begin, begin + source.size(), ret));
127-
EXPECT_EQ(16256, ret);
128-
ret = 0;
129-
130-
source = {static_cast<char>(0x89), static_cast<char>(0x80), static_cast<char>(0x80),
131-
static_cast<char>(0x80), 0x01};
132-
begin = source.data();
133-
EXPECT_TRUE(WasmUtil::parseVarint(begin, begin + source.size(), ret));
134-
EXPECT_EQ(268435465, ret);
135-
}
136-
137110
} // namespace common
138111
} // namespace proxy_wasm

0 commit comments

Comments
 (0)