diff --git a/cpp/include/cuopt/linear_programming/cuopt_c.h b/cpp/include/cuopt/linear_programming/cuopt_c.h index 4426b640de..7930fee32d 100644 --- a/cpp/include/cuopt/linear_programming/cuopt_c.h +++ b/cpp/include/cuopt/linear_programming/cuopt_c.h @@ -959,7 +959,7 @@ cuopt_int_t cuOptGetErrorStatus(cuOptSolution solution, cuopt_int_t* error_statu * @param[out] error_string_ptr - A pointer to a char that on output will contain the * error string. * - * @param[in] error_string_size - Size of the char buffer/ + * @param[in] error_string_size - Size of the char buffer. Must be positive. * * @return A status code indicating success or failure. */ diff --git a/cpp/src/pdlp/cuopt_c.cpp b/cpp/src/pdlp/cuopt_c.cpp index fa27e4504b..b663e9078a 100644 --- a/cpp/src/pdlp/cuopt_c.cpp +++ b/cpp/src/pdlp/cuopt_c.cpp @@ -1174,6 +1174,7 @@ cuopt_int_t cuOptGetErrorString(cuOptSolution solution, { if (solution == nullptr) { return CUOPT_INVALID_ARGUMENT; } if (error_string_ptr == nullptr) { return CUOPT_INVALID_ARGUMENT; } + if (error_string_size <= 0) { return CUOPT_INVALID_ARGUMENT; } solution_and_stream_view_t* solution_and_stream_view = static_cast(solution); std::string error_string = solution_and_stream_view->get_solution()->get_error_status().what(); diff --git a/cpp/tests/linear_programming/c_api_tests/c_api_tests.cpp b/cpp/tests/linear_programming/c_api_tests/c_api_tests.cpp index 9a92f7a310..0e33f3494b 100644 --- a/cpp/tests/linear_programming/c_api_tests/c_api_tests.cpp +++ b/cpp/tests/linear_programming/c_api_tests/c_api_tests.cpp @@ -14,6 +14,8 @@ #include #include +#include +#include #include #include @@ -107,6 +109,25 @@ TEST(c_api, solve_time_bb_preemption) TEST(c_api, bad_parameter_name) { EXPECT_EQ(test_bad_parameter_name(), CUOPT_INVALID_ARGUMENT); } +TEST(c_api, get_error_string_rejects_non_positive_buffer_size) +{ + using cuopt::linear_programming::cpu_lp_solution_t; + using cuopt::linear_programming::memory_backend_t; + using cuopt::linear_programming::pdlp_termination_status_t; + using cuopt::linear_programming::solution_and_stream_view_t; + + solution_and_stream_view_t solution_handle(false, memory_backend_t::CPU); + solution_handle.lp_solution_interface_ptr = new cpu_lp_solution_t( + pdlp_termination_status_t::NumericalError, + cuopt::logic_error("validation failed", cuopt::error_type_t::ValidationError)); + + char error_string[32] = {}; + EXPECT_EQ(cuOptGetErrorString(&solution_handle, error_string, 0), CUOPT_INVALID_ARGUMENT); + EXPECT_EQ(cuOptGetErrorString(&solution_handle, error_string, -1), CUOPT_INVALID_ARGUMENT); + EXPECT_EQ(cuOptGetErrorString(&solution_handle, error_string, sizeof(error_string)), + CUOPT_SUCCESS); +} + TEST(c_api, mip_get_callbacks_only) { EXPECT_EQ(test_mip_get_callbacks_only(), CUOPT_SUCCESS); } TEST(c_api, mip_get_set_callbacks) { EXPECT_EQ(test_mip_get_set_callbacks(), CUOPT_SUCCESS); }