Skip to content
This repository was archived by the owner on Oct 4, 2019. It is now read-only.

Commit f8da6e7

Browse files
authored
Merge pull request #1016 from GolosChain/fix-unpack
Fix unpack() early memory allocation
2 parents 5893b3a + 198862f commit f8da6e7

3 files changed

Lines changed: 98 additions & 6 deletions

File tree

libraries/chain/include/golos/chain/steem_object_types.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ namespace fc {
172172
}
173173

174174
template<typename Stream, typename T>
175-
inline void unpack(Stream &s, chainbase::object_id<T> &id) {
175+
inline void unpack(Stream &s, chainbase::object_id<T> &id, uint32_t = 0) {
176176
s.read((char *)&id._id, sizeof(id._id));
177177
}
178178
}
@@ -189,16 +189,16 @@ namespace fc {
189189
}
190190

191191
template<typename T>
192-
inline void unpack(const golos::chain::buffer_type &raw, T &v) {
192+
inline void unpack(const golos::chain::buffer_type &raw, T &v, uint32_t depth = 0) {
193193
datastream<const char *> ds(raw.data(), raw.size());
194-
unpack(ds, v);
194+
unpack(ds, v, depth);
195195
}
196196

197197
template<typename T>
198-
inline T unpack(const golos::chain::buffer_type &raw) {
198+
inline T unpack(const golos::chain::buffer_type &raw, uint32_t depth = 0) {
199199
T v;
200200
datastream<const char *> ds(raw.data(), raw.size());
201-
unpack(ds, v);
201+
unpack(ds, v, depth);
202202
return v;
203203
}
204204
}

tests/tests/serialization_tests.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,5 +314,97 @@ BOOST_FIXTURE_TEST_SUITE(serialization_tests, clean_database_fixture)
314314
FC_LOG_AND_RETHROW();
315315
}
316316

317+
BOOST_AUTO_TEST_CASE(unpack_clear_test) { try {
318+
std::stringstream ss1;
319+
std::stringstream ss2;
320+
321+
signed_block b1;
322+
323+
for (int i = 0; i < 10; i++) {
324+
signed_transaction tx;
325+
326+
vote_operation op;
327+
op.voter = "alice";
328+
op.author = "bob";
329+
op.permlink = "permlink1";
330+
op.weight = STEEMIT_100_PERCENT;
331+
tx.operations.push_back(op);
332+
333+
vote_operation op2;
334+
op2.voter = "charlie";
335+
op2.author = "sam";
336+
op2.permlink = "permlink2";
337+
op2.weight = STEEMIT_100_PERCENT;
338+
tx.operations.push_back(op2);
339+
340+
tx.ref_block_num = 1000;
341+
tx.ref_block_prefix = 1000000000;
342+
tx.expiration = fc::time_point_sec(1514764800 + i);
343+
344+
b1.transactions.push_back(tx);
345+
}
346+
347+
signed_block b2;
348+
349+
for (int i = 0; i < 20; i++) {
350+
signed_transaction tx;
351+
vote_operation op;
352+
op.voter = "dave";
353+
op.author = "greg";
354+
op.permlink = "foobar";
355+
op.weight = STEEMIT_100_PERCENT/2;
356+
tx.ref_block_num = 4000;
357+
tx.ref_block_prefix = 4000000000;
358+
tx.expiration = fc::time_point_sec(1714764800 + i);
359+
tx.operations.push_back(op);
360+
361+
b2.transactions.push_back(tx);
362+
}
363+
364+
fc::raw::pack(ss2, b2);
365+
fc::raw::pack(ss1, b1);
366+
367+
signed_block unpacked_block;
368+
fc::raw::unpack(ss2, unpacked_block);
369+
370+
// This operation should completely overwrite signed block 'b2'
371+
fc::raw::unpack(ss1, unpacked_block);
372+
373+
BOOST_REQUIRE(b1.transactions.size() == unpacked_block.transactions.size());
374+
for (size_t i = 0; i < unpacked_block.transactions.size(); i++) {
375+
signed_transaction tx = unpacked_block.transactions[i];
376+
BOOST_REQUIRE(unpacked_block.transactions[i].operations.size() == b1.transactions[i].operations.size());
377+
378+
vote_operation op = tx.operations[0].get<vote_operation>();
379+
BOOST_REQUIRE(op.voter == "alice");
380+
BOOST_REQUIRE(op.author == "bob");
381+
BOOST_REQUIRE(op.permlink == "permlink1");
382+
BOOST_REQUIRE(op.weight == STEEMIT_100_PERCENT);
383+
384+
vote_operation op2 = tx.operations[1].get<vote_operation>();
385+
BOOST_REQUIRE(op2.voter == "charlie");
386+
BOOST_REQUIRE(op2.author == "sam");
387+
BOOST_REQUIRE(op2.permlink == "permlink2");
388+
BOOST_REQUIRE(op2.weight == STEEMIT_100_PERCENT);
389+
390+
BOOST_REQUIRE(tx.ref_block_num == 1000);
391+
BOOST_REQUIRE(tx.ref_block_prefix == 1000000000);
392+
BOOST_REQUIRE(tx.expiration == fc::time_point_sec(1514764800 + i));
393+
}
394+
} FC_LOG_AND_RETHROW(); }
395+
396+
BOOST_AUTO_TEST_CASE(unpack_recursion_test) { try {
397+
std::stringstream ss;
398+
int recursion_level = 100000;
399+
uint64_t allocation_per_level = 500000;
400+
for (int i = 0; i < recursion_level; i++) {
401+
fc::raw::pack(ss, unsigned_int(allocation_per_level));
402+
fc::raw::pack(ss, static_cast<uint8_t>(variant::array_type));
403+
}
404+
std::vector<fc::variant> v;
405+
STEEMIT_REQUIRE_THROW(fc::raw::unpack(ss, v), fc::assert_exception);
406+
} FC_LOG_AND_RETHROW(); }
407+
408+
317409
BOOST_AUTO_TEST_SUITE_END()
318410
#endif

0 commit comments

Comments
 (0)