From f4a3ef3adb9678ab99554e1cff9d12ea96e4b94b Mon Sep 17 00:00:00 2001 From: Bastian Dehn Date: Sat, 25 Oct 2025 19:27:36 +0200 Subject: [PATCH] add validation for string and int --- src/kds_s2000w_handler.h | 4 +-- src/kds_s2000w_handler_opts.c | 45 +++++++++++++++++++++++----- src/kds_s2000w_handler_opts.h | 4 +-- src/kds_s2000w_net.c | 4 +-- tests/kds_s2000w_net_set_opt_tests.c | 34 ++++++++++++++++++++- 5 files changed, 76 insertions(+), 15 deletions(-) diff --git a/src/kds_s2000w_handler.h b/src/kds_s2000w_handler.h index c391f6d..1d7080f 100644 --- a/src/kds_s2000w_handler.h +++ b/src/kds_s2000w_handler.h @@ -63,8 +63,8 @@ connection_state_t kds_s2000w_handler_open(const char* devicename, void** handle void kds_s2000w_handler_close(handler_t* h); void kds_s2000w_handler_recreate_session(handler_t* h); -void kds_s2000w_handler_opts_get_option(handler_t* handle, uint32_t option, void* value, int32_t* info); -void kds_s2000w_handler_opts_set_option(handler_t* handle, uint32_t option, void* value, int32_t* info); +int32_t kds_s2000w_handler_opts_get_option(handler_t* handle, uint32_t option, void* value, int32_t* info); +int32_t kds_s2000w_handler_opts_set_option(handler_t* handle, uint32_t option, void* value, int32_t* info); void kds_s2000w_handler_start_scan(const handler_t* h); void kds_s2000w_handler_stop_scan(const handler_t* h); diff --git a/src/kds_s2000w_handler_opts.c b/src/kds_s2000w_handler_opts.c index 60e58b8..a6ffc7b 100644 --- a/src/kds_s2000w_handler_opts.c +++ b/src/kds_s2000w_handler_opts.c @@ -15,6 +15,11 @@ enum { RELOAD_PARAMS = 4 }; +enum { + GOOD = 0, + INVAL = 4 +}; + void _kds_s2000w_handler_opts_write_value_to_json(json_object* value_object, SANE_Value_Type value_type, void* value) { if (value_type == SANE_TYPE_INT || value_type == SANE_TYPE_BOOL) { @@ -130,6 +135,25 @@ json_object* _kds_s2000w_handler_opts_load_config(handler_t* h) return config; } +bool _kds_s2000w_opts_validate(SANE_Option_Descriptor* descriptor, const void* value) +{ + if (descriptor->constraint_type == SANE_CONSTRAINT_RANGE) { + const int32_t* int_value = (const int32_t*) value; + bool valid = *int_value >= descriptor->constraint.range->min; + return valid && *int_value <= descriptor->constraint.range->max; + } + + if (descriptor->constraint_type == SANE_CONSTRAINT_STRING_LIST) { + const char* str_value = (const char*) value; + for (int32_t i = 0; descriptor->constraint.string_list[i] != NULL; i++) { + if (strcmp(descriptor->constraint.string_list[i], str_value) == 0) + return true; + } + } + + return false; +} + void _kds_s2000w_handler_opts_set_valid_coord_x(option_descriptor_t* descriptor, handler_t* h) { bool valid = h->coord->offset_x >= 0 && h->coord->offset_x <= 75; @@ -443,7 +467,7 @@ void _kds_s2000w_handler_opts_set_depends_opts(const handler_t* h, } } -void kds_s2000w_handler_opts_get_option(handler_t* h, uint32_t option, void* value, int32_t* info) +int32_t kds_s2000w_handler_opts_get_option(handler_t* h, uint32_t option, void* value, int32_t* info) { json_object* config = _kds_s2000w_handler_opts_load_config(h); @@ -451,7 +475,7 @@ void kds_s2000w_handler_opts_get_option(handler_t* h, uint32_t option, void* val if (strcmp(descriptor->config_name, OPTION_COUNT) == 0) { int32_t* int_value = (int32_t*) value; *int_value = kds_s2000w_option_descriptors_get_max_option_count(); - return; + return GOOD; } json_object* value_object = json_object_object_get(config, descriptor->config_name); @@ -461,7 +485,7 @@ void kds_s2000w_handler_opts_get_option(handler_t* h, uint32_t option, void* val h->coord->offset_x = json_object_get_int(value_object); uint32_t pixel = kds_s2000w_pixel_converter_tenth_inch_to_pixel(GUI_DPI, h->coord->offset_x); *int_value = pixel; - return; + return GOOD; } if (strcmp(descriptor->config_name, IMAGE_OFFSET_Y) == 0) { @@ -469,7 +493,7 @@ void kds_s2000w_handler_opts_get_option(handler_t* h, uint32_t option, void* val h->coord->offset_y = json_object_get_int(value_object); uint32_t pixel = kds_s2000w_pixel_converter_tenth_inch_to_pixel(GUI_DPI, h->coord->offset_y); *int_value = pixel; - return; + return GOOD; } if (strcmp(descriptor->config_name, IMAGE_WIDTH) == 0) { @@ -480,7 +504,7 @@ void kds_s2000w_handler_opts_get_option(handler_t* h, uint32_t option, void* val uint32_t width_pixel = kds_s2000w_pixel_converter_tenth_inch_to_pixel(GUI_DPI, h->coord->width); uint32_t offset_x_pixel = kds_s2000w_pixel_converter_tenth_inch_to_pixel(GUI_DPI, tenth_inch_offset_x); *int_value = offset_x_pixel + width_pixel; - return; + return GOOD; } if (strcmp(descriptor->config_name, IMAGE_HEIGHT) == 0) { @@ -491,16 +515,17 @@ void kds_s2000w_handler_opts_get_option(handler_t* h, uint32_t option, void* val uint32_t height_pixel = kds_s2000w_pixel_converter_tenth_inch_to_pixel(GUI_DPI, h->coord->height); uint32_t offset_y_pixel = kds_s2000w_pixel_converter_tenth_inch_to_pixel(GUI_DPI, tenth_inch_offset_y); *int_value = offset_y_pixel + height_pixel; - return; + return GOOD; } _kds_s2000w_handler_opts_write_value(value_object, descriptor->descriptor->type, value); + return GOOD; } -void kds_s2000w_handler_opts_set_option(handler_t* h, uint32_t option, void* value, int32_t* info) +int32_t kds_s2000w_handler_opts_set_option(handler_t* h, uint32_t option, void* value, int32_t* info) { if (h->scan_status->state == STARTED) - return; + return GOOD; json_object* config = _kds_s2000w_handler_opts_load_config(h); option_descriptor_t* descriptor = kds_s2000w_option_descriptors_full_get_by_number(option); @@ -525,6 +550,10 @@ void kds_s2000w_handler_opts_set_option(handler_t* h, uint32_t option, void* val if (h->profile > PROFILE_MIN) _kds_s2000w_handler_opts_set_depends_opts(h, descriptor->config_name, config); + if (!_kds_s2000w_opts_validate(descriptor->descriptor, value)) + return INVAL; + _kds_s2000w_handler_opts_set_info_option(descriptor, info); _kds_s2000w_handler_opts_set_options(h); + return GOOD; } \ No newline at end of file diff --git a/src/kds_s2000w_handler_opts.h b/src/kds_s2000w_handler_opts.h index 4c0a276..75ccd69 100644 --- a/src/kds_s2000w_handler_opts.h +++ b/src/kds_s2000w_handler_opts.h @@ -3,7 +3,7 @@ #include #include "kds_s2000w_handler.h" -void kds_s2000w_handler_opts_get_option(handler_t* h, uint32_t option, void* value, int32_t* info); -void kds_s2000w_handler_opts_set_option(handler_t* h, uint32_t option, void* value, int32_t* info); +int32_t kds_s2000w_handler_opts_get_option(handler_t* h, uint32_t option, void* value, int32_t* info); +int32_t kds_s2000w_handler_opts_set_option(handler_t* h, uint32_t option, void* value, int32_t* info); #endif \ No newline at end of file diff --git a/src/kds_s2000w_net.c b/src/kds_s2000w_net.c index fd8a688..6292392 100644 --- a/src/kds_s2000w_net.c +++ b/src/kds_s2000w_net.c @@ -127,10 +127,10 @@ SANE_Status sane_kds_s2000w_net_control_option(SANE_Handle handle, handler_t* h = (handler_t*) handle; if (action == SANE_ACTION_GET_VALUE) - kds_s2000w_handler_opts_get_option(h, option, value, info); + return kds_s2000w_handler_opts_get_option(h, option, value, info); if (action == SANE_ACTION_SET_VALUE) - kds_s2000w_handler_opts_set_option(h, option, value, info); + return kds_s2000w_handler_opts_set_option(h, option, value, info); return SANE_STATUS_GOOD; } diff --git a/tests/kds_s2000w_net_set_opt_tests.c b/tests/kds_s2000w_net_set_opt_tests.c index d3f3937..a8e97fe 100644 --- a/tests/kds_s2000w_net_set_opt_tests.c +++ b/tests/kds_s2000w_net_set_opt_tests.c @@ -166,11 +166,43 @@ void kds_s2000w_net_set_option_int(void** state) set_value = NULL; } +void kds_s2000w_net_set_invalid_option_string(void** state) +{ + int32_t* info = malloc(sizeof(int32_t)); + if (info == NULL) + return; + + response_t* resp = (response_t*) *state; + handler_t* h = kds_s2000w_handler_init(); + *info = 0; + response_t* set_opt_resp = kds_s2000w_client_response_init(); + set_opt_resp->code = 200; + + will_return(mock_response, resp); + will_return(__wrap_kds_s2000w_client_get_option, 0); + will_return(mock_response, set_opt_resp); + will_return(__wrap_kds_s2000w_client_set_option, 0); + expect_function_call(__wrap_kds_s2000w_client_get_option); + expect_function_call(__wrap_kds_s2000w_client_set_option); + + SANE_Status status = sane_kds_s2000w_net_control_option(h, 3, SANE_ACTION_SET_VALUE, "Bunt", info); + + assert_int_equal(status, SANE_STATUS_INVAL); + + kds_s2000w_client_response_free(set_opt_resp); + set_opt_resp = NULL; + kds_s2000w_handler_free(h); + h = NULL; + free(info); + info = NULL; +} + int main() { const struct CMUnitTest net_tests[] = { cmocka_unit_test_setup_teardown(kds_s2000w_net_set_option_string, setup_default_option, teardown_default_option), - cmocka_unit_test_setup_teardown(kds_s2000w_net_set_option_int, setup_default_option, teardown_default_option) + cmocka_unit_test_setup_teardown(kds_s2000w_net_set_option_int, setup_default_option, teardown_default_option), + cmocka_unit_test_setup_teardown(kds_s2000w_net_set_invalid_option_string, setup_default_option, teardown_default_option) }; return cmocka_run_group_tests(net_tests, NULL, NULL); -- 2.47.3