Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UCS/CONFIG: fixed crash on incorrect value set #5987

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/ucs/config/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -1033,9 +1033,12 @@ ucs_config_parser_set_value_internal(void *opts, ucs_config_field_t *fields,
const char *name, const char *value,
const char *table_prefix, int recurse)
{
char value_buf[256] = "";
ucs_config_field_t *field, *sub_fields;
size_t prefix_len;
ucs_status_t status;
ucs_status_t UCS_V_UNUSED status_restore;
int UCS_V_UNUSED ret;
unsigned count;
void *var;

Expand Down Expand Up @@ -1079,9 +1082,17 @@ ucs_config_parser_set_value_internal(void *opts, ucs_config_field_t *fields,
return UCS_ERR_NO_ELEM;
}

/* backup current value to restore it in case if new value
* is not accepted */
ret = field->parser.write(value_buf, sizeof(value_buf) - 1, var,
field->parser.arg);
ucs_assert(ret != 0); /* write success */
ucs_config_parser_release_field(field, var);
status = ucs_config_parser_parse_field(field, value, var);
if (status != UCS_OK) {
status_restore = ucs_config_parser_parse_field(field, value_buf, var);
/* current value must be valid */
ucs_assert(status_restore == UCS_OK);
return status;
}
++count;
Expand Down
36 changes: 36 additions & 0 deletions test/gtest/ucs/test_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,14 @@ ucs_config_field_t car_opts_table[] = {
static std::vector<std::string> config_err_exp_str;

class test_config : public ucs::test {
public:
test_config() {
m_num_errors = 0;
}

protected:
static int m_num_errors;

static ucs_log_func_rc_t
config_error_handler(const char *file, unsigned line, const char *function,
ucs_log_level_t level,
Expand All @@ -246,6 +253,22 @@ class test_config : public ucs::test {
return UCS_LOG_FUNC_RC_CONTINUE;
}

static ucs_log_func_rc_t
config_error_suppress(const char *file, unsigned line, const char *function,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can reuse wrap_errors_logger ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically yes, but in this case we can't check if error is handled - there is no errors counter in wrap_errors_logger

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we call wrap_errors_logger() after counting, to print err message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, wrapped

ucs_log_level_t level,
const ucs_log_component_config_t *comp_conf,
const char *message, va_list ap)
{
// Ignore errors that invalid input parameters as it is expected
if (level == UCS_LOG_LEVEL_ERROR) {
m_num_errors++;
return wrap_errors_logger(file, line, function, level, comp_conf,
message, ap);
}

return UCS_LOG_FUNC_RC_CONTINUE;
}

/*
* Wrapper class for car options parser.
*/
Expand Down Expand Up @@ -377,6 +400,8 @@ class test_config : public ucs::test {
}
};

int test_config::m_num_errors;

UCS_TEST_F(test_config, parse_default) {
car_opts opts(UCS_DEFAULT_ENV_PREFIX, "TEST");

Expand Down Expand Up @@ -457,6 +482,17 @@ UCS_TEST_F(test_config, set_get) {

opts.set("VIN", "123456");
EXPECT_EQ(123456UL, opts->vin);

/* try to set incorrect value - color should not be updated */
{
scoped_log_handler log_handler_vars(config_error_suppress);
opts.set("COLOR", "magenta");
}

EXPECT_EQ(COLOR_WHITE, opts->color);
EXPECT_EQ(std::string(color_names[COLOR_WHITE]),
std::string(opts.get("COLOR")));
EXPECT_EQ(1, m_num_errors);
}

UCS_TEST_F(test_config, set_get_with_table_prefix) {
Expand Down