From 55412c4f3d3486d28fe337b919e7fddc2f93e1b4 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Thu, 11 Oct 2018 15:22:12 +0300 Subject: [PATCH 01/14] Add new source file to test target --- src/test/include.am | 1 + src/test/test.c | 1 + src/test/test.h | 1 + src/test/test_parsecommon.c | 44 +++++++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 src/test/test_parsecommon.c diff --git a/src/test/include.am b/src/test/include.am index 1055cd0a81..dd2986c67c 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -182,6 +182,7 @@ src_test_test_SOURCES += \ src/test/test_x509.c \ src/test/test_helpers.c \ src/test/test_dns.c \ + src/test/test_parsecommon.c \ src/test/testing_common.c \ src/test/testing_rsakeys.c \ src/ext/tinytest.c diff --git a/src/test/test.c b/src/test/test.c index 70d91e3967..56eb153289 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -926,5 +926,6 @@ struct testgroup_t testgroups[] = { { "util/thread/", thread_tests }, { "util/handle/", handle_tests }, { "dns/", dns_tests }, + { "parsecommon/", parsecommon_tests }, END_OF_GROUPS }; diff --git a/src/test/test.h b/src/test/test.h index a46fedf3e0..281551aa69 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -266,6 +266,7 @@ extern struct testcase_t dns_tests[]; extern struct testcase_t handle_tests[]; extern struct testcase_t sr_tests[]; extern struct testcase_t x509_tests[]; +extern struct testcase_t parsecommon_tests[]; extern struct testcase_t slow_crypto_tests[]; extern struct testcase_t slow_util_tests[]; diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c new file mode 100644 index 0000000000..f152450f5a --- /dev/null +++ b/src/test/test_parsecommon.c @@ -0,0 +1,44 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "core/or/or.h" +#include "test/test.h" +#include "lib/memarea/memarea.h" +#include "lib/encoding/binascii.h" +#include "feature/dirparse/parsecommon.h" +#include "test/log_test_helpers.h" + +static void +test_parsecommon_tokenize_string_null(void *arg) +{ + + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + const char *str_with_null = "a\0bccccccccc"; + + int retval = + tokenize_string(area, str_with_null, + str_with_null + 3, + tokens, NULL, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + +#define PARSECOMMON_TEST(name) \ + { #name, test_parsecommon_ ## name, 0, NULL, NULL } + +struct testcase_t parsecommon_tests[] = { + PARSECOMMON_TEST(tokenize_string_null), + END_OF_TESTCASES +}; + From 7829e3a86875da16e3d7ac55be85145bd672fc12 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Fri, 12 Oct 2018 14:19:40 +0300 Subject: [PATCH 02/14] First testcase for get_next_token() --- src/test/test_parsecommon.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index f152450f5a..ba778d9969 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -34,11 +34,38 @@ test_parsecommon_tokenize_string_null(void *arg) return; } +static void +test_parsecommon_get_next_token_success(void *arg) +{ + memarea_t *area = memarea_new(); + const char *str = "uptime 1024"; + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t table = T01("uptime", K_UPTIME, GE(1), NO_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &table); + + tt_int_op(token->tp, OP_EQ, K_UPTIME); + tt_int_op(token->n_args, OP_EQ, 1); + tt_str_op(*(token->args), OP_EQ, "1024"); + tt_assert(!token->object_type); + tt_int_op(token->object_size, OP_EQ, 0); + tt_assert(!token->object_body); + + tt_ptr_op(*s, OP_EQ, end); + + done: + memarea_drop_all(area); + return; +} + #define PARSECOMMON_TEST(name) \ { #name, test_parsecommon_ ## name, 0, NULL, NULL } struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(tokenize_string_null), + PARSECOMMON_TEST(get_next_token_success), END_OF_TESTCASES }; From 5c891dba770b752d16f7e7cea8f61f15abd09ef5 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Fri, 12 Oct 2018 15:48:38 +0300 Subject: [PATCH 03/14] Test argument concatenation in get_next_token() --- src/test/test_parsecommon.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index ba778d9969..b63327ecd1 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -60,12 +60,33 @@ test_parsecommon_get_next_token_success(void *arg) return; } +static void +test_parsecommon_get_next_token_concat_args(void *arg) +{ + memarea_t *area = memarea_new(); + const char *str = "proto A=1 B=2"; + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T01("proto", K_PROTO, CONCAT_ARGS, NO_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, K_PROTO); + tt_int_op(token->n_args, OP_EQ, 1); + tt_str_op(*(token->args), OP_EQ, "A=1 B=2"); + + done: + memarea_drop_all(area); +} + #define PARSECOMMON_TEST(name) \ { #name, test_parsecommon_ ## name, 0, NULL, NULL } struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(tokenize_string_null), PARSECOMMON_TEST(get_next_token_success), + PARSECOMMON_TEST(get_next_token_concat_args), END_OF_TESTCASES }; From 569d8d8cd73987cd0ca126a6f98a75dd34b21137 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Fri, 12 Oct 2018 18:33:27 +0300 Subject: [PATCH 04/14] Test-case for public key parsing using get_next_token() --- src/test/test_parsecommon.c | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index b63327ecd1..519bbf79ea 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -80,6 +80,47 @@ test_parsecommon_get_next_token_concat_args(void *arg) memarea_drop_all(area); } +static void +test_parsecommon_get_next_token_parse_keys(void *arg) +{ + (void)arg; + + memarea_t *area = memarea_new(); + const char *base64_key = + "MIGJAoGBAMDdIya33BfNlHOkzoTKSTT8EjD64waMfUr372syVHiFjHhObwKwGA5u\n" + "sHaMIe9r+Ij/4C1dKyuXkcz3DOl6gWNhTD7dZ89I+Okoh1jWe30jxCiAcywC22p5\n" + "XLhrDkX1A63Z7XCH9ltwU2WMqWsVM98N2GR6MTujP7wtqdLExYN1AgMBAAE=\n"; + char *str; + tor_asprintf(&str, "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "%s" + "-----END RSA PUBLIC KEY-----\n", base64_key); + const char *end = str + strlen(str); + const char **s = (const char **)&str; + const char decoded[128]; + + base64_decode((char *)decoded, sizeof(decoded), base64_key, + strlen(base64_key)); + + token_rule_t rule = T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024); + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, R_IPO_ONION_KEY); + tt_int_op(token->n_args, OP_EQ, 0); + tt_str_op(token->object_type, OP_EQ, "RSA PUBLIC KEY"); + tt_int_op(token->object_size, OP_EQ, 0); + tt_assert(!token->object_body); + tt_assert(token->key); + tt_assert(!token->error); + + // TODO: same with secret key + + + done: + memarea_drop_all(area); +} + #define PARSECOMMON_TEST(name) \ { #name, test_parsecommon_ ## name, 0, NULL, NULL } @@ -87,6 +128,7 @@ struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(tokenize_string_null), PARSECOMMON_TEST(get_next_token_success), PARSECOMMON_TEST(get_next_token_concat_args), + PARSECOMMON_TEST(get_next_token_parse_keys), END_OF_TESTCASES }; From 7764d6dfc914d9a29c706cbcb2b399b09680c9b7 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Fri, 12 Oct 2018 19:19:40 +0300 Subject: [PATCH 05/14] Test RSA private key parsing with get_next_token() --- src/test/test_parsecommon.c | 39 ++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index 519bbf79ea..ffd3902a8d 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -114,8 +114,45 @@ test_parsecommon_get_next_token_parse_keys(void *arg) tt_assert(token->key); tt_assert(!token->error); - // TODO: same with secret key + const char *base64_skey = + "MIICXAIBAAKBgQCwS810a2auH2PQchOBz9smNgjlDu31aq0IYlUohSYbhcv5AJ+d\n" + "DY0nfZWzS+mZPwzL3UiEnTt6PVv7AgoZ5V9ZJWJTKIURjJpkK0mstfJKHKIZhf84\n" + "pmFfRej9GQViB6NLtp1obOXJgJixSlMfw9doDI4NoAnEISCyH/tD77Qs2wIDAQAB\n" + "AoGAbDg8CKkdQOnX9c7xFpCnsE8fKqz9eddgHHNwXw1NFTwOt+2gDWKSMZmv2X5S\n" + "CVZg3owZxf5W0nT0D6Ny2+6nliak7foYAvkD0BsCiBhgftwC0zAo6k5rIbUKB3PJ\n" + "QLFXgpJhqWuXkODyt/hS/GTernR437WVSEGp1bnALqiFabECQQDaqHOxzoWY/nvH\n" + "KrfUi8EhqCnqERlRHwrW0MQZ1RPvF16OPPma+xa+ht/amfh3vYN5tZY82Zm43gGl\n" + "XWL5cZhNAkEAzmdSootYVnqLLLRMfHKXnO1XbaEcA/08MDNKGlSclBJixFenE8jX\n" + "iQsUbHwMJuGONvzWpRGPBP2f8xBd28ZtxwJARY+LZshtpfNniz/ixYJESaHG28je\n" + "xfjbKOW3TQSFV+2WTifFvHEeljQwKMoMyoMGvYRwLCGJjs9JtMLVxsdFjQJBAKwD\n" + "3BBvBQ39TuPQ1zWX4tb7zjMlY83HTFP3Sriq71tP/1QWoL2SUl56B2lp8E6vB/C3\n" + "wsMK4SCNprHRYAd7VZ0CQDKn6Zhd11P94PLs0msybFEh1VXr6CEW/BrxBgbL4ls6\n" + "dbX5XO0z4Ra8gYXgObgimhyMDYO98Idt5+Z3HIdyrSc=\n"; + const char decoded2[128]; + base64_decode((char *)decoded2, sizeof(decoded2), base64_skey, + strlen(base64_skey)); + + char *str2; + tor_asprintf(&str2, "client-key\n" + "-----BEGIN RSA PRIVATE KEY-----\n" + "%s" + "-----END RSA PRIVATE KEY-----\n", base64_skey); + const char *end2 = str2 + strlen(str2); + const char **s2 = (const char **)&str2; + + token_rule_t rule2 = T01("client-key", C_CLIENT_KEY, NO_ARGS, + NEED_SKEY_1024); + + directory_token_t *token2 = get_next_token(area, s2, end2, &rule2); + + tt_int_op(token2->tp, OP_EQ, C_CLIENT_KEY); + tt_int_op(token2->n_args, OP_EQ, 0); + tt_str_op(token2->object_type, OP_EQ, "RSA PRIVATE KEY"); + tt_int_op(token2->object_size, OP_EQ, 0); + tt_assert(!token2->object_body); + tt_assert(token2->key); + tt_assert(!token->error); done: memarea_drop_all(area); From 38a7033d3378a7b0cdc68258ebcd0e53371e8f24 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Mon, 15 Oct 2018 17:44:40 +0300 Subject: [PATCH 06/14] Fix memory management in test_parsecommon_get_next_token_parse_keys --- src/test/test_parsecommon.c | 41 +++++++++++++++---------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index ffd3902a8d..6b5307619a 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -86,25 +86,22 @@ test_parsecommon_get_next_token_parse_keys(void *arg) (void)arg; memarea_t *area = memarea_new(); - const char *base64_key = + const char *str = + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" "MIGJAoGBAMDdIya33BfNlHOkzoTKSTT8EjD64waMfUr372syVHiFjHhObwKwGA5u\n" "sHaMIe9r+Ij/4C1dKyuXkcz3DOl6gWNhTD7dZ89I+Okoh1jWe30jxCiAcywC22p5\n" - "XLhrDkX1A63Z7XCH9ltwU2WMqWsVM98N2GR6MTujP7wtqdLExYN1AgMBAAE=\n"; - char *str; - tor_asprintf(&str, "onion-key\n" - "-----BEGIN RSA PUBLIC KEY-----\n" - "%s" - "-----END RSA PUBLIC KEY-----\n", base64_key); + "XLhrDkX1A63Z7XCH9ltwU2WMqWsVM98N2GR6MTujP7wtqdLExYN1AgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n"; + const char *end = str + strlen(str); const char **s = (const char **)&str; - const char decoded[128]; - - base64_decode((char *)decoded, sizeof(decoded), base64_key, - strlen(base64_key)); + directory_token_t *token = NULL; + directory_token_t *token2 = NULL; token_rule_t rule = T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024); - directory_token_t *token = get_next_token(area, s, end, &rule); + token = get_next_token(area, s, end, &rule); tt_int_op(token->tp, OP_EQ, R_IPO_ONION_KEY); tt_int_op(token->n_args, OP_EQ, 0); @@ -114,7 +111,9 @@ test_parsecommon_get_next_token_parse_keys(void *arg) tt_assert(token->key); tt_assert(!token->error); - const char *base64_skey = + const char *str2 = + "client-key\n" + "-----BEGIN RSA PRIVATE KEY-----\n" "MIICXAIBAAKBgQCwS810a2auH2PQchOBz9smNgjlDu31aq0IYlUohSYbhcv5AJ+d\n" "DY0nfZWzS+mZPwzL3UiEnTt6PVv7AgoZ5V9ZJWJTKIURjJpkK0mstfJKHKIZhf84\n" "pmFfRej9GQViB6NLtp1obOXJgJixSlMfw9doDI4NoAnEISCyH/tD77Qs2wIDAQAB\n" @@ -127,24 +126,16 @@ test_parsecommon_get_next_token_parse_keys(void *arg) "xfjbKOW3TQSFV+2WTifFvHEeljQwKMoMyoMGvYRwLCGJjs9JtMLVxsdFjQJBAKwD\n" "3BBvBQ39TuPQ1zWX4tb7zjMlY83HTFP3Sriq71tP/1QWoL2SUl56B2lp8E6vB/C3\n" "wsMK4SCNprHRYAd7VZ0CQDKn6Zhd11P94PLs0msybFEh1VXr6CEW/BrxBgbL4ls6\n" - "dbX5XO0z4Ra8gYXgObgimhyMDYO98Idt5+Z3HIdyrSc=\n"; + "dbX5XO0z4Ra8gYXgObgimhyMDYO98Idt5+Z3HIdyrSc=\n" + "-----END RSA PRIVATE KEY-----\n"; - const char decoded2[128]; - base64_decode((char *)decoded2, sizeof(decoded2), base64_skey, - strlen(base64_skey)); - - char *str2; - tor_asprintf(&str2, "client-key\n" - "-----BEGIN RSA PRIVATE KEY-----\n" - "%s" - "-----END RSA PRIVATE KEY-----\n", base64_skey); const char *end2 = str2 + strlen(str2); const char **s2 = (const char **)&str2; token_rule_t rule2 = T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024); - directory_token_t *token2 = get_next_token(area, s2, end2, &rule2); + token2 = get_next_token(area, s2, end2, &rule2); tt_int_op(token2->tp, OP_EQ, C_CLIENT_KEY); tt_int_op(token2->n_args, OP_EQ, 0); @@ -155,6 +146,8 @@ test_parsecommon_get_next_token_parse_keys(void *arg) tt_assert(!token->error); done: + if (token) token_clear(token); + if (token2) token_clear(token2); memarea_drop_all(area); } From 6c5ba2662af08c8094e024a2c04141e776d966a6 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Mon, 15 Oct 2018 18:51:08 +0300 Subject: [PATCH 07/14] Test object parsing in get_next_token() --- src/test/test_parsecommon.c | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index 6b5307619a..59e366bc4e 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -151,6 +151,62 @@ test_parsecommon_get_next_token_parse_keys(void *arg) memarea_drop_all(area); } +static void +test_parsecommon_get_next_token_object(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-----\n" + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n" + "-----END SIGNATURE-----\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, K_DIRECTORY_SIGNATURE); + tt_int_op(token->n_args, OP_EQ, 2); + tt_str_op(token->args[0], OP_EQ, + "0232AF901C31A04EE9848595AF9BB7620D4C5B2E"); + tt_str_op(token->args[1], OP_EQ, + "CD1FD971855430880D3C31E0331C5C55800C2F79"); + + tt_assert(!token->error); + + char decoded[256]; + const char *signature = + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n"; + tt_assert(signature); + size_t signature_len = strlen(signature); + base64_decode(decoded, sizeof(decoded), signature, signature_len); + + tt_str_op(token->object_type, OP_EQ, "SIGNATURE"); + tt_int_op(token->object_size, OP_EQ, 256); + tt_mem_op(token->object_body, OP_EQ, decoded, 256); + + tt_assert(!token->key); + + done: + memarea_drop_all(area); +} + #define PARSECOMMON_TEST(name) \ { #name, test_parsecommon_ ## name, 0, NULL, NULL } @@ -159,6 +215,7 @@ struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(get_next_token_success), PARSECOMMON_TEST(get_next_token_concat_args), PARSECOMMON_TEST(get_next_token_parse_keys), + PARSECOMMON_TEST(get_next_token_object), END_OF_TESTCASES }; From 81731a290d2a806047901c1835afb557533a0350 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Mon, 15 Oct 2018 20:01:42 +0300 Subject: [PATCH 08/14] Unit-test some error conditions in get_next_token() --- src/test/test_parsecommon.c | 173 ++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index 59e366bc4e..d8719747e2 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -207,6 +207,173 @@ test_parsecommon_get_next_token_object(void *arg) memarea_drop_all(area); } +static void +test_parsecommon_get_next_token_err_too_many_args(void *arg) +{ + memarea_t *area = memarea_new(); + const char *str = "uptime 1024 1024 1024"; + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t table = T01("uptime", K_UPTIME, EQ(1), NO_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &table); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Too many arguments to uptime"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_too_few_args(void *arg) +{ + memarea_t *area = memarea_new(); + const char *str = "uptime"; + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t table = T01("uptime", K_UPTIME, EQ(1), NO_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &table); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Too few arguments to uptime"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_obj_missing_endline(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-----\n" + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Malformed object: missing object end line"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_bad_beginline(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-Z---\n" + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n" + "-----END SIGNATURE-----\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Malformed object: bad begin line"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_tag_mismatch(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-----\n" + "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n" + "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n" + "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n" + "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n" + "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n" + "Ua9DEZB9KbJHVX1rGShrLA==\n" + "-----END SOMETHINGELSE-----\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, + "Malformed object: mismatched end tag SIGNATURE"); + + done: + memarea_drop_all(area); + return; +} + +static void +test_parsecommon_get_next_token_err_bad_base64(void *arg) +{ + memarea_t *area = memarea_new(); + + const char *str = + "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E " + "CD1FD971855430880D3C31E0331C5C55800C2F79\n" + "-----BEGIN SIGNATURE-----\n" + "%%@%%%%%%%!!!'\n" + "-----END SIGNATURE-----\n"; + + const char *end = str + strlen(str); + const char **s = &str; + token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE, + GE(2), NEED_OBJ); + (void)arg; + + directory_token_t *token = get_next_token(area, s, end, &rule); + + tt_int_op(token->tp, OP_EQ, ERR_); + tt_str_op(token->error, OP_EQ, "Malformed object: bad base64-encoded data"); + + done: + memarea_drop_all(area); + return; +} + #define PARSECOMMON_TEST(name) \ { #name, test_parsecommon_ ## name, 0, NULL, NULL } @@ -216,6 +383,12 @@ struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(get_next_token_concat_args), PARSECOMMON_TEST(get_next_token_parse_keys), PARSECOMMON_TEST(get_next_token_object), + PARSECOMMON_TEST(get_next_token_err_too_many_args), + PARSECOMMON_TEST(get_next_token_err_too_few_args), + PARSECOMMON_TEST(get_next_token_err_obj_missing_endline), + PARSECOMMON_TEST(get_next_token_err_bad_beginline), + PARSECOMMON_TEST(get_next_token_err_tag_mismatch), + PARSECOMMON_TEST(get_next_token_err_bad_base64), END_OF_TESTCASES }; From 78c446af7ef9900c31e84496a4547550d4c191e2 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Tue, 16 Oct 2018 14:53:04 +0300 Subject: [PATCH 09/14] Unit-test multiple line parsing with tokenize_string() --- src/test/test_parsecommon.c | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index d8719747e2..0c754a8fee 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -34,6 +34,51 @@ test_parsecommon_tokenize_string_null(void *arg) return; } +static void +test_parsecommon_tokenize_string_multiple_lines(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T01("uptime", K_UPTIME, GE(1), NO_OBJ), + T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ), + T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ), + END_OF_TABLE, + }; + + char *str = tor_strdup( + "hibernating 0\nuptime 1024\n" + "published 2018-10-15 10:00:00\n"); + + int retval = + tokenize_string(area, str, NULL, + tokens, table, 0); + + tt_int_op(smartlist_len(tokens), OP_EQ, 3); + directory_token_t *token = smartlist_get(tokens, 0); + + tt_int_op(token->tp, OP_EQ, K_HIBERNATING); + + token = smartlist_get(tokens, 1); + + tt_int_op(token->tp, OP_EQ, K_UPTIME); + + token = smartlist_get(tokens, 2); + + tt_int_op(token->tp, OP_EQ, K_PUBLISHED); + + tt_int_op(retval, OP_EQ, 0); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + static void test_parsecommon_get_next_token_success(void *arg) { @@ -379,6 +424,7 @@ test_parsecommon_get_next_token_err_bad_base64(void *arg) struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(tokenize_string_null), + PARSECOMMON_TEST(tokenize_string_multiple_lines), PARSECOMMON_TEST(get_next_token_success), PARSECOMMON_TEST(get_next_token_concat_args), PARSECOMMON_TEST(get_next_token_parse_keys), From 7c8bf2f7c7adbae3b0f56631c2a2c036076b322d Mon Sep 17 00:00:00 2001 From: rl1987 Date: Tue, 16 Oct 2018 15:22:48 +0300 Subject: [PATCH 10/14] Add testcase for too few elements in tokenize_string() input --- src/test/test_parsecommon.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index 0c754a8fee..e68d0fb884 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -79,6 +79,36 @@ test_parsecommon_tokenize_string_multiple_lines(void *arg) return; } +static void +test_parsecommon_tokenize_string_min_cnt(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T01("uptime", K_UPTIME, EQ(2), NO_OBJ), + T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ), + END_OF_TABLE, + }; + + // Missing "uptime" + char *str = tor_strdup("uptime 1024\nhibernating 0\n"); + + int retval = + tokenize_string(area, str, NULL, + tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + static void test_parsecommon_get_next_token_success(void *arg) { @@ -425,6 +455,7 @@ test_parsecommon_get_next_token_err_bad_base64(void *arg) struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(tokenize_string_null), PARSECOMMON_TEST(tokenize_string_multiple_lines), + PARSECOMMON_TEST(tokenize_string_min_cnt), PARSECOMMON_TEST(get_next_token_success), PARSECOMMON_TEST(get_next_token_concat_args), PARSECOMMON_TEST(get_next_token_parse_keys), From 1a4edceee9049d19a97b08dc28e87fa346d02536 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Tue, 16 Oct 2018 15:31:47 +0300 Subject: [PATCH 11/14] Add testcase for too many elements in tokenize_string() input --- src/test/test_parsecommon.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index e68d0fb884..182f6fba5d 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -109,6 +109,37 @@ test_parsecommon_tokenize_string_min_cnt(void *arg) return; } +static void +test_parsecommon_tokenize_string_max_cnt(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T01("uptime", K_UPTIME, EQ(1), NO_OBJ), + T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ), + END_OF_TABLE, + }; + + // "uptime" expected once, but occurs twice in input. + char *str = tor_strdup( + "uptime 1024\nuptime 2048\nhibernating 0\n"); + + int retval = + tokenize_string(area, str, NULL, + tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + static void test_parsecommon_get_next_token_success(void *arg) { @@ -456,6 +487,7 @@ struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(tokenize_string_null), PARSECOMMON_TEST(tokenize_string_multiple_lines), PARSECOMMON_TEST(tokenize_string_min_cnt), + PARSECOMMON_TEST(tokenize_string_max_cnt), PARSECOMMON_TEST(get_next_token_success), PARSECOMMON_TEST(get_next_token_concat_args), PARSECOMMON_TEST(get_next_token_parse_keys), From f10d664fd14b318fba23c7290c800590d0a474b4 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Tue, 16 Oct 2018 15:54:11 +0300 Subject: [PATCH 12/14] Test AT_END checking in tokenize_string() --- src/test/test_parsecommon.c | 62 +++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index 182f6fba5d..13e4ac8c7f 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -140,6 +140,66 @@ test_parsecommon_tokenize_string_max_cnt(void *arg) return; } +static void +test_parsecommon_tokenize_string_at_start(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ), + T01("uptime", K_UPTIME, EQ(1), NO_OBJ), + END_OF_TABLE, + }; + + // "client-name" is not the first line. + char *str = tor_strdup( + "uptime 1024\nclient-name Alice\n"); + + int retval = + tokenize_string(area, str, NULL, tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + +static void +test_parsecommon_tokenize_string_at_end(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + T1_END("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ), + T01("uptime", K_UPTIME, EQ(1), NO_OBJ), + END_OF_TABLE, + }; + + // "client-name" is not the last line. + char *str = tor_strdup( + "client-name Alice\nuptime 1024\n"); + + int retval = + tokenize_string(area, str, NULL, tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + static void test_parsecommon_get_next_token_success(void *arg) { @@ -488,6 +548,8 @@ struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(tokenize_string_multiple_lines), PARSECOMMON_TEST(tokenize_string_min_cnt), PARSECOMMON_TEST(tokenize_string_max_cnt), + PARSECOMMON_TEST(tokenize_string_at_start), + PARSECOMMON_TEST(tokenize_string_at_end), PARSECOMMON_TEST(get_next_token_success), PARSECOMMON_TEST(get_next_token_concat_args), PARSECOMMON_TEST(get_next_token_parse_keys), From 7fd82a4570c4c3ea887c02190a54e424eb5f4c5f Mon Sep 17 00:00:00 2001 From: rl1987 Date: Tue, 16 Oct 2018 17:39:52 +0300 Subject: [PATCH 13/14] One testcase for annotation handling in tokenize_string() --- src/test/test_parsecommon.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c index 13e4ac8c7f..7ce4b71b00 100644 --- a/src/test/test_parsecommon.c +++ b/src/test/test_parsecommon.c @@ -200,6 +200,33 @@ test_parsecommon_tokenize_string_at_end(void *arg) return; } +static void +test_parsecommon_tokenize_string_no_annotations(void *arg) +{ + memarea_t *area = memarea_new(); + smartlist_t *tokens = smartlist_new(); + + (void)arg; + + token_rule_t table[] = { + A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ), + END_OF_TABLE, + }; + + char *str = tor_strdup("@last-listed 2018-09-21 15:30:03\n"); + + int retval = + tokenize_string(area, str, NULL, tokens, table, 0); + + tt_int_op(retval, OP_EQ, -1); + + done: + tor_free(str); + memarea_drop_all(area); + smartlist_free(tokens); + return; +} + static void test_parsecommon_get_next_token_success(void *arg) { @@ -550,6 +577,7 @@ struct testcase_t parsecommon_tests[] = { PARSECOMMON_TEST(tokenize_string_max_cnt), PARSECOMMON_TEST(tokenize_string_at_start), PARSECOMMON_TEST(tokenize_string_at_end), + PARSECOMMON_TEST(tokenize_string_no_annotations), PARSECOMMON_TEST(get_next_token_success), PARSECOMMON_TEST(get_next_token_concat_args), PARSECOMMON_TEST(get_next_token_parse_keys), From 65864be9bc59fb3743d2cebf497d0a4268596f95 Mon Sep 17 00:00:00 2001 From: rl1987 Date: Tue, 16 Oct 2018 17:53:17 +0300 Subject: [PATCH 14/14] Add changes file --- changes/ticket27625 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changes/ticket27625 diff --git a/changes/ticket27625 b/changes/ticket27625 new file mode 100644 index 0000000000..33d40adf34 --- /dev/null +++ b/changes/ticket27625 @@ -0,0 +1,4 @@ + o Testing: + - Write some unit tests for tokenize_string() and + get_next_token() functions. Resolves ticket 27625. +