From d5385e86729a9e1f895be7bd1def3247e1b945f3 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Fri, 17 Nov 2017 15:08:08 -0800 Subject: [PATCH 1/3] libtomlc99/test: walk all TOML input files Problem: TAP test only calls toml_parse() on invalid input files, but failure may occur later during toml_rto*(). As discussed in cktan/tomlc99#4, add code to the test to walk each input file and ensure all elements can be accessed. Remove blacklist entries, except the segfaulting one. --- src/libtomlc99/toml_tap.c | 110 ++++++++++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 10 deletions(-) diff --git a/src/libtomlc99/toml_tap.c b/src/libtomlc99/toml_tap.c index ea0782085012..a342ef85937d 100644 --- a/src/libtomlc99/toml_tap.c +++ b/src/libtomlc99/toml_tap.c @@ -21,6 +21,10 @@ timeout = 1.5E3\n\ " +bool validate_toml_table (toml_table_t *conf, char *errbuf, int errsize); +bool validate_toml_array (toml_array_t *array, char *errbuf, int errsize); +bool validate_toml_value (const char *raw, char *errbuf, int errsize); + void parse_ex1 (void) { char errbuf[255]; @@ -85,6 +89,90 @@ void parse_ex1 (void) free (host); } +bool validate_toml_value (const char *raw, char *errbuf, int errsize) +{ + char *str; + int i; + int64_t i64; + double d; + struct toml_timestamp_t ts; + + if (toml_rtos (raw, &str) == 0) { + free (str); + return true; + } + else if (toml_rtob (raw, &i) == 0) + return true; + else if (toml_rtoi (raw, &i64) == 0) + return true; + else if (toml_rtod (raw, &d) == 0) + return true; + else if (toml_rtots (raw, &ts) == 0) + return true; + + snprintf (errbuf, errsize, "%s is an invalid value", raw); + return false; +} + +bool validate_toml_array (toml_array_t *array, char *errbuf, int errsize) +{ + int i; + const char *raw; + toml_array_t *arr; + toml_table_t *tab; + + switch (toml_array_kind (array)) { + case 'v': + for (i = 0; (raw = toml_raw_at (array, i)); i++) { + if (!validate_toml_value (raw, errbuf, errsize)) + return false; + } + break; + case 'a': + for (i = 0; (arr = toml_array_at (array, i)); i++) { + if (!validate_toml_array (arr, errbuf, errsize)) + return false; + } + break; + case 't': + for (i = 0; (tab = toml_table_at (array, i)); i++) { + if (!validate_toml_table (tab, errbuf, errsize)) + return false; + } + break; + } + return true; +} + +bool validate_toml_table (toml_table_t *conf, char *errbuf, int errsize) +{ + int i; + const char *key; + const char *raw; + toml_array_t *arr; + toml_table_t *tab; + + for (i = 0; (key = toml_key_in (conf, i)); i++) { + if ((raw = toml_raw_in (conf, key))) { // value + if (!validate_toml_value (raw, errbuf, errsize)) + return false; + } + else if ((arr = toml_array_in (conf, key))) { // array + if (!validate_toml_array (arr, errbuf, errsize)) + return false; + } + else if ((tab = toml_table_in (conf, key))) { // table + if (!validate_toml_table (tab, errbuf, errsize)) + return false; + } + else { + snprintf (errbuf, errsize, "key=%s is invalid", key); + return false; + } + } + return true; +} + /* return true if file can be opened and parsing fails */ bool parse_bad_file (const char *path, char *errbuf, int errsize) @@ -98,10 +186,13 @@ bool parse_bad_file (const char *path, char *errbuf, int errsize) } conf = toml_parse_file (fp, errbuf, errsize); if (conf != NULL) { + if (validate_toml_table (conf, errbuf, errsize)) { + toml_free (conf); + fclose (fp); + snprintf (errbuf, errsize, "success"); + return false; + } toml_free (conf); - fclose (fp); - snprintf (errbuf, errsize, "success"); - return false; } fclose (fp); return true; @@ -113,13 +204,7 @@ struct entry { }; const struct entry bad_input_blacklist[] = { - { "datetime-malformed-no-leads.toml", "parses" }, - { "datetime-malformed-no-secs.toml", "parses" }, - { "datetime-malformed-no-t.toml", "parses" }, - { "datetime-malformed-with-milli.toml", "parses" }, - { "float-no-leading-zero.toml", "parses" }, - { "float-no-trailing-digits.toml", "parses" }, - { "table-array-implicit.toml" , "segfault" }, + { "table-array-implicit.toml" , "segfault, cktan/tomlc99#3" }, { NULL, NULL }, }; @@ -178,6 +263,11 @@ bool parse_good_file (const char *path, char *errbuf, int errsize) fclose (fp); return false; } + if (!validate_toml_table (conf, errbuf, errsize)) { + fclose (fp); + toml_free (conf); + return false; + } toml_free (conf); fclose (fp); snprintf (errbuf, errsize, "success"); From b42ed9c6185362e6153597160c494631938cfb5c Mon Sep 17 00:00:00 2001 From: CK Tan Date: Sat, 18 Nov 2017 11:57:45 -0800 Subject: [PATCH 2/3] libtomlc99: fix segfaulting test Pulled from cktan/tomlc99@01ecb88d1. This fixes cktan/tomlc99#3: bad input file causes segfault. --- src/libtomlc99/toml.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libtomlc99/toml.c b/src/libtomlc99/toml.c index 0e00a83affca..669d6d218c77 100644 --- a/src/libtomlc99/toml.c +++ b/src/libtomlc99/toml.c @@ -1140,6 +1140,10 @@ static void parse_select(context_t* ctx) /* [[x.y.z]] -> create z = [] in x.y */ toml_array_t* arr = create_keyarray_in_table(ctx, ctx->curtab, z, 1 /*skip_if_exist*/); + if (!arr) { + e_syntax_error(ctx, z.lineno, "key exists"); + return; + } if (arr->kind == 0) arr->kind = 't'; if (arr->kind != 't') { e_syntax_error(ctx, z.lineno, "array mismatch"); From d169d5597c7974192a9b438bfe50cf795b3a45fd Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Sat, 18 Nov 2017 12:34:28 -0800 Subject: [PATCH 3/3] libtomlc99/test: un-blacklist segfaulting teset After backporting upstream fix, we can un-blacklist the test input that was triggering segfault. --- src/libtomlc99/toml_tap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libtomlc99/toml_tap.c b/src/libtomlc99/toml_tap.c index a342ef85937d..af0ed2afb195 100644 --- a/src/libtomlc99/toml_tap.c +++ b/src/libtomlc99/toml_tap.c @@ -204,7 +204,6 @@ struct entry { }; const struct entry bad_input_blacklist[] = { - { "table-array-implicit.toml" , "segfault, cktan/tomlc99#3" }, { NULL, NULL }, };