未验证 提交 322f0fc8 编写于 作者: A arhag 提交者: GitHub

Merge pull request #3644 from EOSIO/gh#3635-abi-gen-segfault

Gh#3635 abi gen segfault
...@@ -124,7 +124,7 @@ bool abi_generator::inspect_type_methods_for_actions(const Decl* decl) { try { ...@@ -124,7 +124,7 @@ bool abi_generator::inspect_type_methods_for_actions(const Decl* decl) { try {
qt.setLocalFastQualifiers(0); qt.setLocalFastQualifiers(0);
string field_name = p->getNameAsString(); string field_name = p->getNameAsString();
string field_type_name = add_type(qt); string field_type_name = add_type(qt, 0);
field_def struct_field{field_name, field_type_name}; field_def struct_field{field_name, field_type_name};
ABI_ASSERT(is_builtin_type(get_vector_element_type(struct_field.type)) ABI_ASSERT(is_builtin_type(get_vector_element_type(struct_field.type))
...@@ -236,7 +236,7 @@ void abi_generator::handle_decl(const Decl* decl) { try { ...@@ -236,7 +236,7 @@ void abi_generator::handle_decl(const Decl* decl) { try {
auto qt = action_decl->getTypeForDecl()->getCanonicalTypeInternal(); auto qt = action_decl->getTypeForDecl()->getCanonicalTypeInternal();
auto type_name = add_struct(qt); auto type_name = add_struct(qt, "", 0);
ABI_ASSERT(!is_builtin_type(type_name), ABI_ASSERT(!is_builtin_type(type_name),
"A built-in type with the same name exists, try using another name: ${type_name}", ("type_name",type_name)); "A built-in type with the same name exists, try using another name: ${type_name}", ("type_name",type_name));
...@@ -259,7 +259,7 @@ void abi_generator::handle_decl(const Decl* decl) { try { ...@@ -259,7 +259,7 @@ void abi_generator::handle_decl(const Decl* decl) { try {
ABI_ASSERT(table_decl != nullptr); ABI_ASSERT(table_decl != nullptr);
auto qt = table_decl->getTypeForDecl()->getCanonicalTypeInternal(); auto qt = table_decl->getTypeForDecl()->getCanonicalTypeInternal();
auto type_name = add_struct(qt); auto type_name = add_struct(qt, "", 0);
ABI_ASSERT(!is_builtin_type(type_name), ABI_ASSERT(!is_builtin_type(type_name),
"A built-in type with the same name exists, try using another name: ${type_name}", ("type_name",type_name)); "A built-in type with the same name exists, try using another name: ${type_name}", ("type_name",type_name));
...@@ -433,7 +433,11 @@ const struct_def* abi_generator::find_struct(const type_name& name) { ...@@ -433,7 +433,11 @@ const struct_def* abi_generator::find_struct(const type_name& name) {
type_name abi_generator::resolve_type(const type_name& type){ type_name abi_generator::resolve_type(const type_name& type){
const auto* td = find_type(type); const auto* td = find_type(type);
if( td ) { if( td ) {
return resolve_type(td->type); for( auto i = output->types.size(); i > 0; --i ) { // avoid infinite recursion
const type_name& t = td->type;
td = find_type(t);
if( td == nullptr ) return t;
}
} }
return type; return type;
} }
...@@ -505,7 +509,9 @@ string abi_generator::get_type_name(const clang::QualType& qt, bool with_namespa ...@@ -505,7 +509,9 @@ string abi_generator::get_type_name(const clang::QualType& qt, bool with_namespa
return name; return name;
} }
clang::QualType abi_generator::add_typedef(const clang::QualType& tqt) { clang::QualType abi_generator::add_typedef(const clang::QualType& tqt, size_t recursion_depth) {
ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
clang::QualType qt(get_named_type_if_elaborated(tqt)); clang::QualType qt(get_named_type_if_elaborated(tqt));
...@@ -516,7 +522,7 @@ clang::QualType abi_generator::add_typedef(const clang::QualType& tqt) { ...@@ -516,7 +522,7 @@ clang::QualType abi_generator::add_typedef(const clang::QualType& tqt) {
auto underlying_type_name = get_type_name(underlying_type); auto underlying_type_name = get_type_name(underlying_type);
if ( is_vector(underlying_type) ) { if ( is_vector(underlying_type) ) {
underlying_type_name = add_vector(underlying_type); underlying_type_name = add_vector(underlying_type, recursion_depth);
} }
type_def abi_typedef; type_def abi_typedef;
...@@ -531,7 +537,7 @@ clang::QualType abi_generator::add_typedef(const clang::QualType& tqt) { ...@@ -531,7 +537,7 @@ clang::QualType abi_generator::add_typedef(const clang::QualType& tqt) {
} }
if( is_typedef(underlying_type) && !is_builtin_type(get_type_name(underlying_type)) ) if( is_typedef(underlying_type) && !is_builtin_type(get_type_name(underlying_type)) )
return add_typedef(underlying_type); return add_typedef(underlying_type, recursion_depth);
return underlying_type; return underlying_type;
} }
...@@ -568,14 +574,16 @@ const clang::RecordDecl::field_range abi_generator::get_struct_fields(const clan ...@@ -568,14 +574,16 @@ const clang::RecordDecl::field_range abi_generator::get_struct_fields(const clan
return record_type->getDecl()->fields(); return record_type->getDecl()->fields();
} }
string abi_generator::add_vector(const clang::QualType& vqt) { string abi_generator::add_vector(const clang::QualType& vqt, size_t recursion_depth) {
ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
clang::QualType qt(get_named_type_if_elaborated(vqt)); clang::QualType qt(get_named_type_if_elaborated(vqt));
auto vector_element_type = get_vector_element_type(qt); auto vector_element_type = get_vector_element_type(qt);
ABI_ASSERT(!is_vector(vector_element_type), "Only one-dimensional arrays are supported"); ABI_ASSERT(!is_vector(vector_element_type), "Only one-dimensional arrays are supported");
add_type(vector_element_type); add_type(vector_element_type, recursion_depth);
auto vector_element_type_str = translate_type(get_type_name(vector_element_type)); auto vector_element_type_str = translate_type(get_type_name(vector_element_type));
vector_element_type_str += "[]"; vector_element_type_str += "[]";
...@@ -583,7 +591,9 @@ string abi_generator::add_vector(const clang::QualType& vqt) { ...@@ -583,7 +591,9 @@ string abi_generator::add_vector(const clang::QualType& vqt) {
return vector_element_type_str; return vector_element_type_str;
} }
string abi_generator::add_type(const clang::QualType& tqt) { string abi_generator::add_type(const clang::QualType& tqt, size_t recursion_depth) {
ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
clang::QualType qt(get_named_type_if_elaborated(tqt)); clang::QualType qt(get_named_type_if_elaborated(tqt));
...@@ -596,7 +606,7 @@ string abi_generator::add_type(const clang::QualType& tqt) { ...@@ -596,7 +606,7 @@ string abi_generator::add_type(const clang::QualType& tqt) {
} }
if( is_typedef(qt) ) { if( is_typedef(qt) ) {
qt = add_typedef(qt); qt = add_typedef(qt, recursion_depth);
if( is_builtin_type(translate_type(get_type_name(qt))) ) { if( is_builtin_type(translate_type(get_type_name(qt))) ) {
return type_name; return type_name;
} }
...@@ -604,12 +614,12 @@ string abi_generator::add_type(const clang::QualType& tqt) { ...@@ -604,12 +614,12 @@ string abi_generator::add_type(const clang::QualType& tqt) {
} }
if( is_vector(qt) ) { if( is_vector(qt) ) {
auto vector_type_name = add_vector(qt); auto vector_type_name = add_vector(qt, recursion_depth);
return is_type_def ? type_name : vector_type_name; return is_type_def ? type_name : vector_type_name;
} }
if( is_struct(qt) ) { if( is_struct(qt) ) {
return add_struct(qt, full_type_name); return add_struct(qt, full_type_name, recursion_depth);
} }
ABI_ASSERT(false, "types can only be: vector, struct, class or a built-in type. (${type}) ", ("type",get_type_name(qt))); ABI_ASSERT(false, "types can only be: vector, struct, class or a built-in type. (${type}) ", ("type",get_type_name(qt)));
...@@ -623,7 +633,9 @@ clang::QualType abi_generator::get_named_type_if_elaborated(const clang::QualTyp ...@@ -623,7 +633,9 @@ clang::QualType abi_generator::get_named_type_if_elaborated(const clang::QualTyp
return qt; return qt;
} }
string abi_generator::add_struct(const clang::QualType& sqt, string full_name) { string abi_generator::add_struct(const clang::QualType& sqt, string full_name, size_t recursion_depth) {
ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
clang::QualType qt(get_named_type_if_elaborated(sqt)); clang::QualType qt(get_named_type_if_elaborated(sqt));
...@@ -653,7 +665,7 @@ string abi_generator::add_struct(const clang::QualType& sqt, string full_name) { ...@@ -653,7 +665,7 @@ string abi_generator::add_struct(const clang::QualType& sqt, string full_name) {
const auto* record_type = base_qt->getAs<clang::RecordType>(); const auto* record_type = base_qt->getAs<clang::RecordType>();
if( record_type && is_struct(base_qt) && !record_type->getDecl()->field_empty() ) { if( record_type && is_struct(base_qt) && !record_type->getDecl()->field_empty() ) {
ABI_ASSERT(total_bases == 0, "Multiple inheritance not supported - ${type}", ("type",full_name)); ABI_ASSERT(total_bases == 0, "Multiple inheritance not supported - ${type}", ("type",full_name));
base_name = add_type(base_qt); base_name = add_type(base_qt, recursion_depth);
++total_bases; ++total_bases;
} }
++bitr; ++bitr;
...@@ -664,7 +676,7 @@ string abi_generator::add_struct(const clang::QualType& sqt, string full_name) { ...@@ -664,7 +676,7 @@ string abi_generator::add_struct(const clang::QualType& sqt, string full_name) {
clang::QualType qt = field->getType(); clang::QualType qt = field->getType();
string field_name = field->getNameAsString(); string field_name = field->getNameAsString();
string field_type_name = add_type(qt); string field_type_name = add_type(qt, recursion_depth);
field_def struct_field{field_name, field_type_name}; field_def struct_field{field_name, field_type_name};
ABI_ASSERT(is_builtin_type(get_vector_element_type(struct_field.type)) ABI_ASSERT(is_builtin_type(get_vector_element_type(struct_field.type))
......
...@@ -159,7 +159,8 @@ namespace eosio { ...@@ -159,7 +159,8 @@ namespace eosio {
* @brief Generates eosio::abi_def struct handling events from ASTConsumer * @brief Generates eosio::abi_def struct handling events from ASTConsumer
*/ */
class abi_generator { class abi_generator {
private: private:
static constexpr size_t max_recursion_depth = 25; // arbitrary depth to prevent infinite recursion
bool verbose; bool verbose;
int optimizations; int optimizations;
abi_def* output; abi_def* output;
...@@ -171,6 +172,7 @@ namespace eosio { ...@@ -171,6 +172,7 @@ namespace eosio {
string target_contract; string target_contract;
vector<string> target_actions; vector<string> target_actions;
ricardian_contracts rc; ricardian_contracts rc;
public: public:
enum optimization { enum optimization {
...@@ -178,7 +180,8 @@ namespace eosio { ...@@ -178,7 +180,8 @@ namespace eosio {
}; };
abi_generator() abi_generator()
:optimizations(0) : verbose(false)
, optimizations(0)
, output(nullptr) , output(nullptr)
, compiler_instance(nullptr) , compiler_instance(nullptr)
, ast_context(nullptr) , ast_context(nullptr)
...@@ -283,17 +286,17 @@ namespace eosio { ...@@ -283,17 +286,17 @@ namespace eosio {
string decl_to_string(clang::Decl* d); string decl_to_string(clang::Decl* d);
bool is_typedef(const clang::QualType& qt); bool is_typedef(const clang::QualType& qt);
QualType add_typedef(const clang::QualType& qt); QualType add_typedef(const clang::QualType& qt, size_t recursion_depth);
bool is_vector(const clang::QualType& qt); bool is_vector(const clang::QualType& qt);
bool is_vector(const string& type_name); bool is_vector(const string& type_name);
string add_vector(const clang::QualType& qt); string add_vector(const clang::QualType& qt, size_t recursion_depth);
bool is_struct(const clang::QualType& qt); bool is_struct(const clang::QualType& qt);
string add_struct(const clang::QualType& qt, string full_type_name=""); string add_struct(const clang::QualType& qt, string full_type_name, size_t recursion_depth);
string get_type_name(const clang::QualType& qt, bool no_namespace); string get_type_name(const clang::QualType& qt, bool no_namespace);
string add_type(const clang::QualType& tqt); string add_type(const clang::QualType& tqt, size_t recursion_depth);
bool is_elaborated(const clang::QualType& qt); bool is_elaborated(const clang::QualType& qt);
bool is_struct_specialization(const clang::QualType& qt); bool is_struct_specialization(const clang::QualType& qt);
......
...@@ -3297,6 +3297,31 @@ BOOST_AUTO_TEST_CASE(abi_type_redefine_to_name) ...@@ -3297,6 +3297,31 @@ BOOST_AUTO_TEST_CASE(abi_type_redefine_to_name)
} FC_LOG_AND_RETHROW() } } FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE(abi_type_nested_in_vector)
{ try {
// inifinite loop in types
const char* repeat_abi = R"=====(
{
"types": [],
"structs": [{
"name": "store_t",
"base": "",
"fields": [{
"name": "id",
"type": "uint64"
},{
"name": "childs",
"type": "store_t[]"
}],
"actions": [],
"tables": []
}
)=====";
BOOST_CHECK_THROW( abi_serializer abis(fc::json::from_string(repeat_abi).as<abi_def>()), fc::exception );
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE(abi_account_name_in_eosio_abi) BOOST_AUTO_TEST_CASE(abi_account_name_in_eosio_abi)
{ try { { try {
// inifinite loop in types // inifinite loop in types
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册