From 527daab6b73410a5bc88a28d3e0ede46a28c8219 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 9 Mar 2018 18:49:21 +0100 Subject: [PATCH] Moved format_string from variant.cpp to string.cpp (it is declared in string.hpp), added handling of recursion errors --- src/exception.cpp | 23 +++++++++++---- src/log/gelf_appender.cpp | 11 +++++-- src/string.cpp | 56 ++++++++++++++++++++++++++++++++++++ src/variant.cpp | 60 --------------------------------------- 4 files changed, 83 insertions(+), 67 deletions(-) diff --git a/src/exception.cpp b/src/exception.cpp index 0e0b956..e173be4 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -162,7 +162,14 @@ namespace fc for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) { ss << itr->get_message() <<"\n"; //fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; - ss << " " << json::to_string( itr->get_data() )<<"\n"; + try + { + ss << " " << json::to_string( itr->get_data() )<<"\n"; + } + catch( const fc::assert_exception& e ) + { + ss << "ERROR: Failed to convert log data to string!\n"; + } ss << " " << itr->get_context().to_string(); ++itr; if( itr != my->_elog.end() ) ss<<"\n"; @@ -256,10 +263,16 @@ namespace fc ("source_lineno", lineno) ("expr", expr) ; - std::cout - << "FC_ASSERT triggered: " - << fc::json::to_string( assert_trip_info ) << "\n"; - return; + try + { + std::cout + << "FC_ASSERT triggered: " + << fc::json::to_string( assert_trip_info ) << "\n"; + } + catch( const fc::assert_exception& e ) + { // this should never happen. assert_trip_info is flat. + std::cout << "ERROR: Failed to convert info to string?!\n"; + } } bool enable_record_assert_trip = false; diff --git a/src/log/gelf_appender.cpp b/src/log/gelf_appender.cpp index b88387c..2f14d78 100644 --- a/src/log/gelf_appender.cpp +++ b/src/log/gelf_appender.cpp @@ -128,8 +128,15 @@ namespace fc if (!context.get_task_name().empty()) gelf_message["_task_name"] = context.get_task_name(); - string gelf_message_as_string = json::to_string(gelf_message); - //unsigned uncompressed_size = gelf_message_as_string.size(); + string gelf_message_as_string; + try + { + gelf_message_as_string = json::to_string(gelf_message); + } + catch( const fc::assert_exception& e ) + { + gelf_message_as_string = "{\"level\":3,\"short_message\":\"ERROR while generating log message\"}"; + } gelf_message_as_string = zlib_compress(gelf_message_as_string); // graylog2 expects the zlib header to be 0x78 0x9c diff --git a/src/string.cpp b/src/string.cpp index 84edb88..e04f439 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #include @@ -256,6 +258,60 @@ namespace fc { } } + string format_string( const string& format, const variant_object& args ) + { + stringstream ss; + size_t prev = 0; + auto next = format.find( '$' ); + while( prev < format.size() ) + { + ss << format.substr( prev, next == string::npos ? string::npos : next - prev ); + + // if we got to the end, return it. + if( next == size_t(string::npos) || next == format.size() ) + return ss.str(); + + // if we are not at the end, then update the start + prev = next + 1; + + if( format[prev] == '{' ) + { + // if the next char is a open, then find close + next = format.find( '}', prev ); + // if we found close... + if( next != string::npos ) + { + // the key is between prev and next + string key = format.substr( prev+1, (next-prev-1) ); + + auto val = args.find( key ); + if( val != args.end() ) + { + if( val->value().is_object() || val->value().is_array() ) + { + try + { + ss << json::to_string( val->value() ); + } + catch( const fc::assert_exception& e ) + { + ss << "[\"ERROR_WHILE_CONVERTING_VALUE_TO_STRING\"]"; + } + } + else + ss << val->value().as_string(); + } + else + ss << "${"<& vo ) // vo = std::vector( b64.c_str(), b64.c_str() + b64.size() ); } -string format_string( const string& format, const variant_object& args ) -{ - stringstream ss; - size_t prev = 0; - auto next = format.find( '$' ); - while( prev != size_t(string::npos) && prev < size_t(format.size()) ) - { - ss << format.substr( prev, size_t(next-prev) ); - - // if we got to the end, return it. - if( next == size_t(string::npos) ) - return ss.str(); - - // if we are not at the end, then update the start - prev = next + 1; - - if( format[prev] == '{' ) - { - // if the next char is a open, then find close - next = format.find( '}', prev ); - // if we found close... - if( next != size_t(string::npos) ) - { - // the key is between prev and next - string key = format.substr( prev+1, (next-prev-1) ); - - auto val = args.find( key ); - if( val != args.end() ) - { - if( val->value().is_object() || val->value().is_array() ) - { - ss << json::to_string( val->value() ); - } - else - { - ss << val->value().as_string(); - } - } - else - { - ss << "${"<