Skip to content

Commit 887b129

Browse files
Ref #88 Review updates: check retval of intrinsic
Ensure the buffer was adequately large for the response and if not, allocate sufficient space and call intrinsic again.
1 parent f7b206f commit 887b129

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

libraries/eosiolib/contracts/eosio/action.hpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,18 +174,38 @@ namespace eosio {
174174
inline checksum256 get_code_hash( name account, code_hash_result* full_result = nullptr ) {
175175
if (full_result == nullptr)
176176
full_result = (code_hash_result*)alloca(sizeof(code_hash_result));
177+
constexpr size_t max_stack_buffer_size = 50;
177178

178-
// Packed size is dynamic, so we don't know what it'll be. Try to have plenty of space.
179-
auto struct_buffer_size = sizeof(code_hash_result)*2;
179+
// Packed size of this struct will virtually always be less than the struct size; always less after padding
180+
auto struct_buffer_size = sizeof(code_hash_result);
180181
char* struct_buffer = (char*)alloca(struct_buffer_size);
181182

182183
using VersionType = decltype(code_hash_result::struct_version);
183184
const VersionType STRUCT_VERSION = 0;
184-
internal_use_do_not_use::get_code_hash(account.value, STRUCT_VERSION, struct_buffer, struct_buffer_size);
185+
auto response_size =
186+
internal_use_do_not_use::get_code_hash(account.value, STRUCT_VERSION, struct_buffer, struct_buffer_size);
187+
// Safety check: in this case, response size should never exceed our buffer, but just in case...
188+
bool buffer_on_heap = false;
189+
if (response_size > struct_buffer_size) {
190+
// Slow path: allocate an adequate buffer and try again
191+
// No need to deallocate struct_buffer since it was alloca'd
192+
if (response_size > max_stack_buffer_size) {
193+
struct_buffer = (char*)malloc(response_size);
194+
buffer_on_heap = true;
195+
} else {
196+
struct_buffer = (char*)alloca(response_size);
197+
}
198+
internal_use_do_not_use::get_code_hash(account.value, STRUCT_VERSION, struct_buffer, struct_buffer_size);
199+
}
200+
185201
check(unpack<VersionType>(struct_buffer, struct_buffer_size) == STRUCT_VERSION,
186202
"Hypervisor returned unexpected code hash struct version");
187203
unpack(*full_result, struct_buffer, struct_buffer_size);
188204

205+
// If struct_buffer is heap allocated, we must free it
206+
if (buffer_on_heap)
207+
free(struct_buffer);
208+
189209
return full_result->code_hash;
190210
}
191211

0 commit comments

Comments
 (0)