From e4e287516c13d8c7d1f51cdab7697c21110d730b Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Tue, 30 Jun 2026 14:31:15 -0500 Subject: [PATCH] fix: guard non-string JSON type fields before strcmp in C API driver parse_cuopt_json() read variable_types[] and the constraint_bounds.types[] fallback via cJSON valuestring and passed the result straight to strcmp(). cJSON sets valuestring to NULL for non-string nodes (numbers, bools, null, arrays, objects), so a non-string element produced strcmp(NULL, ...), which dereferences a NULL pointer and crashes (SIGSEGV; UBSan nonnull violation) on untrusted cuOpt-JSON input. Guard both sinks with cJSON_IsString() plus a NULL check before each strcmp, falling back to the default (CONTINUOUS variable / unconstrained row) for non-string entries. Verified under ASan/UBSan: both a number-valued variable_types element and a number-valued constraint_bounds.types element crashed before the fix and parse cleanly after. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Ramakrishna Prabhu --- benchmark_apis/c_api_driver/cuopt_json_to_c_api.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/benchmark_apis/c_api_driver/cuopt_json_to_c_api.c b/benchmark_apis/c_api_driver/cuopt_json_to_c_api.c index c926420..d4900ff 100644 --- a/benchmark_apis/c_api_driver/cuopt_json_to_c_api.c +++ b/benchmark_apis/c_api_driver/cuopt_json_to_c_api.c @@ -361,15 +361,15 @@ int parse_cuopt_json(const char* filename, ProblemData* data) { cJSON* type_item = types->child; while (bound_item && type_item && i < data->num_constraints) { cuopt_float_t bound_value = parse_numeric_value(bound_item); - char* type = type_item->valuestring; - - if (strcmp(type, "L") == 0) { // Less than or equal + char* type = cJSON_IsString(type_item) ? type_item->valuestring : NULL; + + if (type && strcmp(type, "L") == 0) { // Less than or equal data->constraint_lower_bounds[i] = -CUOPT_INFINITY; data->constraint_upper_bounds[i] = bound_value; - } else if (strcmp(type, "G") == 0) { // Greater than or equal + } else if (type && strcmp(type, "G") == 0) { // Greater than or equal data->constraint_lower_bounds[i] = bound_value; data->constraint_upper_bounds[i] = CUOPT_INFINITY; - } else if (strcmp(type, "E") == 0) { // Equal + } else if (type && strcmp(type, "E") == 0) { // Equal data->constraint_lower_bounds[i] = bound_value; data->constraint_upper_bounds[i] = bound_value; } @@ -431,8 +431,8 @@ int parse_cuopt_json(const char* filename, ProblemData* data) { i = 0; cJSON* type_item; cJSON_ArrayForEach(type_item, variable_types) { - char* type_str = type_item->valuestring; - if (strcmp(type_str, "I") == 0) { + char* type_str = cJSON_IsString(type_item) ? type_item->valuestring : NULL; + if (type_str && strcmp(type_str, "I") == 0) { data->variable_types[i] = CUOPT_INTEGER; } else { data->variable_types[i] = CUOPT_CONTINUOUS;