@@ -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