oatpp / oatpp

🌱Light and powerful C++ web framework for highly scalable and resource-efficient web application. It's zero-dependency and easy-portable.
https://oatpp.io/
Apache License 2.0
7.81k stars 1.3k forks source link

Web server crashing with segmentation fault when one of the request params is specified null #817

Open AntGuy04 opened 1 year ago

AntGuy04 commented 1 year ago

The whole webserver crashes, if one of the json body params is specified as null with the error message as segmentation fault. I have caught all errors using a try catch in the controller, but this is not getting caught. In the object mapper I have kept objectMapper->getDeserializer()->getConfig()->allowUnknownFields = false. Is there any way to get a 4xx/5xx error instead if one of the params is specifically given the value null instead of the whole web server crashing. Eg request body where failure occurs: {"url":null, "strength":1}

My DTO is as follows:

include OATPP_CODEGEN_BEGIN(DTO)

class URLEncodeRequest : public oatpp::DTO {

DTO_INIT(URLEncodeRequest, DTO)

DTO_FIELD(String, url);

DTO_FIELD(Int8, strength);

};

include OATPP_CODEGEN_END(DTO)

And the controller is as follows:

ADD_CORS(image2QR, "*", "GET, POST, OPTIONS", "DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range", "1728000") ENDPOINT("POST", "/encodeURL", image2QR, BODY_DTO(Object, URLEncodeRequest)) { try{ auto dto = URLEncodeRequest::createShared(); EncodeResponse encodeResponse; std::string url = image2QRRequest->url->c_str(); int strength = image2QRRequest->strength; encodeResponse.encodedURL = encodeResponse.encodeURL(url, strength); return createDtoResponse(Status::CODE_200, encodeResponse.encodedURL); } catch(std::exception &e){ auto statusDto = StatusDto::createShared(); statusDto->status="Internal Server Error"; statusDto->code=500; statusDto->message="Unknown Internal Server Error"; std::cout<<e.what(); return createDtoResponse(Status::CODE_500, statusDto); }catch(...) { auto statusDto = StatusDto::createShared(); statusDto->status="Internal Server Error"; statusDto->code=500; statusDto->message="Unknown Internal Server Error"; return createDtoResponse(Status::CODE_500, statusDto); }

AppComponent.cpp OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionProvider)([] { return oatpp::network::tcp::server::ConnectionProvider::createShared({"0.0.0.0", 8000, oatpp::network::Address::IP_4}); }());

/**
 *  Create Router component
 */
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, httpRouter)([] {
    return oatpp::web::server::HttpRouter::createShared();
}());

/**
 *  Create ObjectMapper component to serialize/deserialize DTOs in Contoller's API
 */
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, apiObjectMapper)([] {
    auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared();
    objectMapper->getDeserializer()->getConfig()->allowUnknownFields = false;
    return objectMapper;
}());

/**
 *  Create ConnectionHandler component which uses Router component to route requests
 */
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, serverConnectionHandler)([] {
    OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router); // get Router component
    OATPP_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper); // get ObjectMapper component
    auto connectionHandler = oatpp::web::server::HttpConnectionHandler::createShared(router);
    connectionHandler->setErrorHandler(std::make_shared<ErrorHandler>(objectMapper));
    return connectionHandler;
}());

And this along with the controller is being called in the main function. / Register Components in scope of run() method / AppComponent components;

/* Get router component */
OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);

/* Create Image2QRController and add all of its endpoints to router */
router->addController(std::make_shared<URLEncodeController>());

/* Get connection handler component */
OATPP_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, connectionHandler);

/* Get connection provider component */
OATPP_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, connectionProvider);

/* Create server which takes provided TCP connections and passes them to HTTP connection handler */
oatpp::network::Server server(connectionProvider, connectionHandler);

/* Print info about server port */
OATPP_LOGI("MyApp", "Server running on port %s", connectionProvider->getProperty("port").getData());

/* Run server */
server.run();
doufu3344 commented 1 year ago

You should check if a pointer can be dereferenced before dereferencing it, since dereferencing null pointers is a system thing which cannot be caught.

....
          std::string url;
          if(image2QRRequest->url)  // <<-----------
            url = image2QRRequest->url->c_str();
          int strength;
          if(image2QRRequest->strength)  // <<----------- Int8 is not int
            strength = image2QRRequest->strength;
....