Skip to content

Commit

Permalink
Merge branch 'fix/empty-vehicles-segfault'
Browse files Browse the repository at this point in the history
  • Loading branch information
jcoupey committed Nov 14, 2024
2 parents 8df975f + 49dd485 commit 671ab6c
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

- Crash when input is valid JSON but not an object (#1172)
- Capacity array check consistency (#1086)
- Segfault when using the C++ API with empty vehicles (#1187)

#### Internals

Expand Down
23 changes: 15 additions & 8 deletions src/structures/vroom/input/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,19 @@ void Input::check_job(Job& job) {
_all_locations_have_coords && job.location.has_coordinates();
}

void Input::run_basic_checks() const {
if (vehicles.empty()) {
throw InputException("No vehicle defined.");
}
if (jobs.empty()) {
throw InputException("No task defined.");
}
if (_geometry && !_all_locations_have_coords) {
// Early abort when info is required with missing coordinates.
throw InputException("Route geometry request with missing coordinates.");
}
}

void Input::add_job(const Job& job) {
if (job.type != JOB_TYPE::SINGLE) {
throw InputException("Wrong job type.");
Expand Down Expand Up @@ -1106,10 +1119,7 @@ Solution Input::solve(unsigned nb_searches,
unsigned nb_thread,
const Timeout& timeout,
const std::vector<HeuristicParameters>& h_param) {
if (_geometry && !_all_locations_have_coords) {
// Early abort when info is required with missing coordinates.
throw InputException("Route geometry request with missing coordinates.");
}
run_basic_checks();

if (_has_initial_routes) {
set_vehicle_steps_ranks();
Expand Down Expand Up @@ -1189,10 +1199,7 @@ Solution Input::solve(unsigned nb_searches,

Solution Input::check(unsigned nb_thread) {
#if USE_LIBGLPK
if (_geometry && !_all_locations_have_coords) {
// Early abort when info is required with missing coordinates.
throw InputException("Route geometry request with missing coordinates.");
}
run_basic_checks();

set_vehicle_steps_ranks();

Expand Down
2 changes: 2 additions & 0 deletions src/structures/vroom/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class Input {
void check_amount_size(const Amount& amount);
void check_job(Job& job);

void run_basic_checks() const;

UserCost check_cost_bound(const Matrix<UserCost>& matrix) const;

void set_skills_compatibility();
Expand Down
33 changes: 17 additions & 16 deletions src/utils/input_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,19 +521,15 @@ void parse(Input& input, const std::string& input_str, bool geometry) {
throw InputException("Input root is not an object.");
}

bool has_jobs = json_input.HasMember("jobs") &&
json_input["jobs"].IsArray() && !json_input["jobs"].Empty();
bool has_shipments = json_input.HasMember("shipments") &&
json_input["shipments"].IsArray() &&
!json_input["shipments"].Empty();
if (!has_jobs && !has_shipments) {
throw InputException("Invalid jobs or shipments.");
}

if (!json_input.HasMember("vehicles") || !json_input["vehicles"].IsArray() ||
json_input["vehicles"].Empty()) {
if (!json_input.HasMember("vehicles") || !json_input["vehicles"].IsArray()) {
throw InputException("Invalid vehicles.");
}
if (json_input["vehicles"].Empty()) {
// This is tested upstream upon solving but we still need to do it
// here to access first vehicle and retrieve amount_size.
throw InputException("No vehicle defined.");
}

const auto& first_vehicle = json_input["vehicles"][0];
check_id(first_vehicle, "vehicle");
bool first_vehicle_has_capacity = (first_vehicle.HasMember("capacity") &&
Expand All @@ -551,16 +547,21 @@ void parse(Input& input, const std::string& input_str, bool geometry) {
input.add_vehicle(get_vehicle(json_vehicle, amount_size));
}

// Add all tasks.
if (has_jobs) {
// Add the jobs.
if (json_input.HasMember("jobs")) {
if (!json_input["jobs"].IsArray()) {
throw InputException("Invalid jobs.");
}

for (rapidjson::SizeType i = 0; i < json_input["jobs"].Size(); ++i) {
input.add_job(get_job(json_input["jobs"][i], amount_size));
}
}

if (has_shipments) {
// Add the shipments.
if (json_input.HasMember("shipments")) {
if (!json_input["shipments"].IsArray()) {
throw InputException("Invalid shipments.");
}

for (rapidjson::SizeType i = 0; i < json_input["shipments"].Size(); ++i) {
auto& json_shipment = json_input["shipments"][i];
check_shipment(json_shipment);
Expand Down

0 comments on commit 671ab6c

Please sign in to comment.