Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crash in boost::coroutine library when used alongside boost::property_tree XML parser

I'm using Simple-Web-Server library for creating simple web service for translation of XML to JSON and vice versa. On its turn it uses several boost libraries as well boost::coroutine among them. For XML<->JSON conversion I'm using boost::property_tree library for intermediate representation. Here is the code:

#include <iostream>
#include <sstream>

#include <server_http.hpp>

#define BOOST_SPIRIT_THREADSAFE
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/xml_parser.hpp>

using namespace std;
using namespace boost::property_tree;

using HttpServer = SimpleWeb::Server<SimpleWeb::HTTP>;

int main()
{
  HttpServer server(8080, 1);

  server.resource["^/json_to_xml$"]["POST"] = [](auto& response, auto request) {
    try
    {
      ptree pt;
      read_json(request->content, pt);
      ostringstream json, xml;
      write_json(json, pt);
      clog << "JSON request content:" << endl << json.str() << endl;
      write_xml(xml, pt, xml_writer_make_settings<ptree::key_type>(' ', 1u));
      clog << "XML response content:" << endl << xml.str() << endl;
      response << "HTTP/1.1 200 OK\r\nContent-Length: " << xml.str().length() << "\r\n\r\n" << xml.str();
    }
    catch(const exception& e)
    {
      cerr << "Error:" << endl << e.what() << endl;
      response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << strlen(e.what()) << "\r\n\r\n" << e.what();
    }
  };

  server.resource["^/xml_to_json$"]["POST"] = [](auto& response, auto request) {
    try
    {
      ptree pt;
      read_xml(request->content, pt, xml_parser::trim_whitespace | xml_parser::no_comments);
      ostringstream xml, json;
      write_xml(xml, pt, xml_writer_make_settings<ptree::key_type>(' ', 1u));
      clog << "XML request content:" << endl << xml.str() << endl;
      write_json(json, pt);
      clog << "JSON response content: " << endl << json.str() << endl;
      response << "HTTP/1.1 200 OK\r\nContent-Length: " << json.str().length() << "\r\n\r\n" << json.str();
    }
    catch(const exception& e)
    {
      cerr << "Error:" << endl << e.what() << endl;
      response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << strlen(e.what()) << "\r\n\r\n" << e.what();
    }
  };

  server.start();

  return 0;
}

JSON to XML conversion works fine but the opposite causes the program to crash. When I'm not using boost::property_tree's XML parser in the server's callback the program works fine. Here is the result of execution. Here is GDB backtrace. And finally here is Valgrind output.

Used version of the boost libraries is 1.58.0 but the same result is observed with the newest version 1.61.0. Version 1.4.2 of the Simple-Web-Server is used.

like image 573
bobeff Avatar asked Oct 18 '22 08:10

bobeff


1 Answers

read_xml() might be overflowing your coroutine's stack; see here about a similar crash traced down to a 64K stack variable inside the rapidxml parser.

EDIT. To summarize the link... the gist of the matter is, the rapidxml parser buried within read_xml allocates 64K on the stack, which overflows the 8K default coroutine stack on Linux. You can try two things... either force that stack variable to be smaller, e.g.,

#define BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE 512
#include <boost/property_tree/xml_parser.hpp>

or allocate a larger stack when the coroutine is spawned (if it's possible to access that through Simple-Web-Server)

like image 134
R. Li Avatar answered Oct 21 '22 05:10

R. Li