tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

test_parsecommon.c (18100B)


      1 /* Copyright (c) 2001-2004, Roger Dingledine.
      2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      4 /* See LICENSE for licensing information */
      5 
      6 #include "core/or/or.h"
      7 #include "test/test.h"
      8 #include "lib/memarea/memarea.h"
      9 #include "lib/encoding/binascii.h"
     10 #include "feature/dirparse/parsecommon.h"
     11 #include "test/log_test_helpers.h"
     12 
     13 static void
     14 test_parsecommon_tokenize_string_null(void *arg)
     15 {
     16 
     17  memarea_t *area = memarea_new();
     18  smartlist_t *tokens = smartlist_new();
     19 
     20  (void)arg;
     21 
     22  const char *str_with_null = "a\0bccccccccc";
     23 
     24  int retval =
     25  tokenize_string(area, str_with_null,
     26                  str_with_null + 3,
     27                  tokens, NULL, 0);
     28 
     29  tt_int_op(retval, OP_EQ, -1);
     30 
     31 done:
     32  memarea_drop_all(area);
     33  smartlist_free(tokens);
     34  return;
     35 }
     36 
     37 static void
     38 test_parsecommon_tokenize_string_multiple_lines(void *arg)
     39 {
     40  memarea_t *area = memarea_new();
     41  smartlist_t *tokens = smartlist_new();
     42 
     43  (void)arg;
     44 
     45  token_rule_t table[] = {
     46          T01("uptime", K_UPTIME, GE(1), NO_OBJ),
     47          T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ),
     48          T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ),
     49          END_OF_TABLE,
     50  };
     51 
     52  char *str = tor_strdup(
     53          "hibernating 0\nuptime 1024\n"
     54          "published 2018-10-15 10:00:00\n");
     55 
     56  int retval =
     57  tokenize_string(area, str, NULL,
     58                  tokens, table, 0);
     59 
     60  tt_int_op(smartlist_len(tokens), OP_EQ, 3);
     61  directory_token_t *token = smartlist_get(tokens, 0);
     62 
     63  tt_int_op(token->tp, OP_EQ, K_HIBERNATING);
     64 
     65  token = smartlist_get(tokens, 1);
     66 
     67  tt_int_op(token->tp, OP_EQ, K_UPTIME);
     68 
     69  token = smartlist_get(tokens, 2);
     70 
     71  tt_int_op(token->tp, OP_EQ, K_PUBLISHED);
     72 
     73  tt_int_op(retval, OP_EQ, 0);
     74 
     75 done:
     76  tor_free(str);
     77  memarea_drop_all(area);
     78  smartlist_free(tokens);
     79  return;
     80 }
     81 
     82 static void
     83 test_parsecommon_tokenize_string_min_cnt(void *arg)
     84 {
     85  memarea_t *area = memarea_new();
     86  smartlist_t *tokens = smartlist_new();
     87 
     88  (void)arg;
     89 
     90  token_rule_t table[] = {
     91          T01("uptime", K_UPTIME, EQ(2), NO_OBJ),
     92          T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ),
     93          END_OF_TABLE,
     94  };
     95 
     96  // Missing "uptime"
     97  char *str = tor_strdup("uptime 1024\nhibernating 0\n");
     98 
     99  int retval =
    100  tokenize_string(area, str, NULL,
    101                  tokens, table, 0);
    102 
    103  tt_int_op(retval, OP_EQ, -1);
    104 
    105 done:
    106  tor_free(str);
    107  memarea_drop_all(area);
    108  smartlist_free(tokens);
    109  return;
    110 }
    111 
    112 static void
    113 test_parsecommon_tokenize_string_max_cnt(void *arg)
    114 {
    115  memarea_t *area = memarea_new();
    116  smartlist_t *tokens = smartlist_new();
    117 
    118  (void)arg;
    119 
    120  token_rule_t table[] = {
    121          T01("uptime", K_UPTIME, EQ(1), NO_OBJ),
    122          T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ),
    123          END_OF_TABLE,
    124  };
    125 
    126  // "uptime" expected once, but occurs twice in input.
    127  char *str = tor_strdup(
    128                  "uptime 1024\nuptime 2048\nhibernating 0\n");
    129 
    130  int retval =
    131  tokenize_string(area, str, NULL,
    132                  tokens, table, 0);
    133 
    134  tt_int_op(retval, OP_EQ, -1);
    135 
    136 done:
    137  tor_free(str);
    138  memarea_drop_all(area);
    139  smartlist_free(tokens);
    140  return;
    141 }
    142 
    143 static void
    144 test_parsecommon_tokenize_string_at_start(void *arg)
    145 {
    146  memarea_t *area = memarea_new();
    147  smartlist_t *tokens = smartlist_new();
    148 
    149  (void)arg;
    150 
    151  token_rule_t table[] = {
    152          T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
    153          T01("uptime", K_UPTIME, EQ(1), NO_OBJ),
    154          END_OF_TABLE,
    155  };
    156 
    157  // "client-name" is not the first line.
    158  char *str = tor_strdup(
    159                  "uptime 1024\nclient-name Alice\n");
    160 
    161  int retval =
    162  tokenize_string(area, str, NULL, tokens, table, 0);
    163 
    164  tt_int_op(retval, OP_EQ, -1);
    165 
    166 done:
    167  tor_free(str);
    168  memarea_drop_all(area);
    169  smartlist_free(tokens);
    170  return;
    171 }
    172 
    173 static void
    174 test_parsecommon_tokenize_string_at_end(void *arg)
    175 {
    176  memarea_t *area = memarea_new();
    177  smartlist_t *tokens = smartlist_new();
    178 
    179  (void)arg;
    180 
    181  token_rule_t table[] = {
    182          T1_END("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
    183          T01("uptime", K_UPTIME, EQ(1), NO_OBJ),
    184          END_OF_TABLE,
    185  };
    186 
    187  // "client-name" is not the last line.
    188  char *str = tor_strdup(
    189                  "client-name Alice\nuptime 1024\n");
    190 
    191  int retval =
    192  tokenize_string(area, str, NULL, tokens, table, 0);
    193 
    194  tt_int_op(retval, OP_EQ, -1);
    195 
    196 done:
    197  tor_free(str);
    198  memarea_drop_all(area);
    199  smartlist_free(tokens);
    200  return;
    201 }
    202 
    203 static void
    204 test_parsecommon_tokenize_string_no_annotations(void *arg)
    205 {
    206  memarea_t *area = memarea_new();
    207  smartlist_t *tokens = smartlist_new();
    208 
    209  (void)arg;
    210 
    211  token_rule_t table[] = {
    212          A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ),
    213          END_OF_TABLE,
    214  };
    215 
    216  char *str = tor_strdup("@last-listed 2018-09-21 15:30:03\n");
    217 
    218  int retval =
    219  tokenize_string(area, str, NULL, tokens, table, 0);
    220 
    221  tt_int_op(retval, OP_EQ, -1);
    222 
    223 done:
    224  tor_free(str);
    225  memarea_drop_all(area);
    226  smartlist_free(tokens);
    227  return;
    228 }
    229 
    230 static void
    231 test_parsecommon_get_next_token_success(void *arg)
    232 {
    233  memarea_t *area = memarea_new();
    234  const char *str = "uptime 1024";
    235  const char *end = str + strlen(str);
    236  const char **s = &str;
    237  token_rule_t table = T01("uptime", K_UPTIME, GE(1), NO_OBJ);
    238  (void)arg;
    239 
    240  directory_token_t *token = get_next_token(area, s, end, &table);
    241 
    242  tt_int_op(token->tp, OP_EQ, K_UPTIME);
    243  tt_int_op(token->n_args, OP_EQ, 1);
    244  tt_str_op(*(token->args), OP_EQ, "1024");
    245  tt_assert(!token->object_type);
    246  tt_int_op(token->object_size, OP_EQ, 0);
    247  tt_assert(!token->object_body);
    248 
    249  tt_ptr_op(*s, OP_EQ, end);
    250 
    251 done:
    252  memarea_drop_all(area);
    253  return;
    254 }
    255 
    256 static void
    257 test_parsecommon_get_next_token_carriage_return(void *arg)
    258 {
    259  memarea_t *area = memarea_new();
    260  smartlist_t *tokens = smartlist_new();
    261 
    262  (void)arg;
    263 
    264  token_rule_t table[] = {
    265          T01("uptime", K_UPTIME, GE(1), NO_OBJ),
    266          T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ),
    267          END_OF_TABLE,
    268  };
    269 
    270  char *str = tor_strdup(
    271          "hibernating 0\r\nuptime 1024\n"
    272          "hibernating 0\ruptime 1024\n");
    273 
    274  int retval =
    275  tokenize_string(area, str, NULL,
    276                  tokens, table, 0);
    277 
    278  tt_int_op(smartlist_len(tokens), OP_EQ, 3);
    279  directory_token_t *token = smartlist_get(tokens, 0);
    280 
    281  tt_int_op(token->tp, OP_EQ, K_HIBERNATING);
    282 
    283  token = smartlist_get(tokens, 1);
    284 
    285  tt_int_op(token->tp, OP_EQ, K_UPTIME);
    286 
    287  token = smartlist_get(tokens, 2);
    288 
    289  tt_int_op(token->tp, OP_EQ, K_HIBERNATING);
    290 
    291  tt_int_op(retval, OP_EQ, -1);
    292 
    293 done:
    294  tor_free(str);
    295  memarea_drop_all(area);
    296  smartlist_free(tokens);
    297  return;
    298 }
    299 
    300 static void
    301 test_parsecommon_get_next_token_concat_args(void *arg)
    302 {
    303  memarea_t *area = memarea_new();
    304  const char *str = "proto A=1 B=2";
    305  const char *end = str + strlen(str);
    306  const char **s = &str;
    307  token_rule_t rule = T01("proto", K_PROTO, CONCAT_ARGS, NO_OBJ);
    308  (void)arg;
    309 
    310  directory_token_t *token = get_next_token(area, s, end, &rule);
    311 
    312  tt_int_op(token->tp, OP_EQ, K_PROTO);
    313  tt_int_op(token->n_args, OP_EQ, 1);
    314  tt_str_op(*(token->args), OP_EQ, "A=1 B=2");
    315 
    316 done:
    317  memarea_drop_all(area);
    318 }
    319 
    320 static void
    321 test_parsecommon_get_next_token_parse_keys(void *arg)
    322 {
    323  (void)arg;
    324 
    325  memarea_t *area = memarea_new();
    326  const char *str =
    327    "onion-key\n"
    328    "-----BEGIN RSA PUBLIC KEY-----\n"
    329    "MIGJAoGBAMDdIya33BfNlHOkzoTKSTT8EjD64waMfUr372syVHiFjHhObwKwGA5u\n"
    330    "sHaMIe9r+Ij/4C1dKyuXkcz3DOl6gWNhTD7dZ89I+Okoh1jWe30jxCiAcywC22p5\n"
    331    "XLhrDkX1A63Z7XCH9ltwU2WMqWsVM98N2GR6MTujP7wtqdLExYN1AgMBAAE=\n"
    332    "-----END RSA PUBLIC KEY-----\n";
    333 
    334  const char *end = str + strlen(str);
    335  const char **s = (const char **)&str;
    336  directory_token_t *token = NULL;
    337  directory_token_t *token2 = NULL;
    338 
    339  token_rule_t rule = T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024);
    340 
    341  token = get_next_token(area, s, end, &rule);
    342  tt_assert(token);
    343 
    344  tt_int_op(token->tp, OP_EQ, R_IPO_ONION_KEY);
    345  tt_int_op(token->n_args, OP_EQ, 0);
    346  tt_str_op(token->object_type, OP_EQ, "RSA PUBLIC KEY");
    347  tt_int_op(token->object_size, OP_EQ, 140);
    348  tt_assert(token->object_body);
    349  tt_assert(token->key);
    350  tt_assert(!token->error);
    351 
    352  const char *str2 =
    353    "client-key\n"
    354    "-----BEGIN RSA PRIVATE KEY-----\n"
    355    "MIICXAIBAAKBgQCwS810a2auH2PQchOBz9smNgjlDu31aq0IYlUohSYbhcv5AJ+d\n"
    356    "DY0nfZWzS+mZPwzL3UiEnTt6PVv7AgoZ5V9ZJWJTKIURjJpkK0mstfJKHKIZhf84\n"
    357    "pmFfRej9GQViB6NLtp1obOXJgJixSlMfw9doDI4NoAnEISCyH/tD77Qs2wIDAQAB\n"
    358    "AoGAbDg8CKkdQOnX9c7xFpCnsE8fKqz9eddgHHNwXw1NFTwOt+2gDWKSMZmv2X5S\n"
    359    "CVZg3owZxf5W0nT0D6Ny2+6nliak7foYAvkD0BsCiBhgftwC0zAo6k5rIbUKB3PJ\n"
    360    "QLFXgpJhqWuXkODyt/hS/GTernR437WVSEGp1bnALqiFabECQQDaqHOxzoWY/nvH\n"
    361    "KrfUi8EhqCnqERlRHwrW0MQZ1RPvF16OPPma+xa+ht/amfh3vYN5tZY82Zm43gGl\n"
    362    "XWL5cZhNAkEAzmdSootYVnqLLLRMfHKXnO1XbaEcA/08MDNKGlSclBJixFenE8jX\n"
    363    "iQsUbHwMJuGONvzWpRGPBP2f8xBd28ZtxwJARY+LZshtpfNniz/ixYJESaHG28je\n"
    364    "xfjbKOW3TQSFV+2WTifFvHEeljQwKMoMyoMGvYRwLCGJjs9JtMLVxsdFjQJBAKwD\n"
    365    "3BBvBQ39TuPQ1zWX4tb7zjMlY83HTFP3Sriq71tP/1QWoL2SUl56B2lp8E6vB/C3\n"
    366    "wsMK4SCNprHRYAd7VZ0CQDKn6Zhd11P94PLs0msybFEh1VXr6CEW/BrxBgbL4ls6\n"
    367    "dbX5XO0z4Ra8gYXgObgimhyMDYO98Idt5+Z3HIdyrSc=\n"
    368    "-----END RSA PRIVATE KEY-----\n";
    369 
    370  const char *end2 = str2 + strlen(str2);
    371  const char **s2 = (const char **)&str2;
    372 
    373  token_rule_t rule2 = T01("client-key", C_CLIENT_KEY, NO_ARGS, OBJ_OK);
    374  token2 = get_next_token(area, s2, end2, &rule2);
    375  tt_assert(token2);
    376  tt_int_op(token2->tp, OP_EQ, C_CLIENT_KEY);
    377  tt_int_op(token2->n_args, OP_EQ, 0);
    378  tt_str_op(token2->object_type, OP_EQ, "RSA PRIVATE KEY");
    379  tt_int_op(token2->object_size, OP_EQ, 608);
    380  tt_assert(token2->object_body);
    381  tt_assert(token2->key == NULL);
    382  tt_assert(!token->error);
    383 
    384 done:
    385  if (token) token_clear(token);
    386  if (token2) token_clear(token2);
    387  memarea_drop_all(area);
    388 }
    389 
    390 static void
    391 test_parsecommon_get_next_token_object(void *arg)
    392 {
    393  memarea_t *area = memarea_new();
    394 
    395  const char *str =
    396    "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E "
    397    "CD1FD971855430880D3C31E0331C5C55800C2F79\n"
    398    "-----BEGIN SIGNATURE-----\n"
    399    "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n"
    400    "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n"
    401    "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n"
    402    "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n"
    403    "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n"
    404    "Ua9DEZB9KbJHVX1rGShrLA==\n"
    405    "-----END SIGNATURE-----\n";
    406 
    407  const char *end = str + strlen(str);
    408  const char **s = &str;
    409  token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE,
    410                        GE(2), NEED_OBJ);
    411  (void)arg;
    412 
    413  directory_token_t *token = get_next_token(area, s, end, &rule);
    414 
    415  tt_int_op(token->tp, OP_EQ, K_DIRECTORY_SIGNATURE);
    416  tt_int_op(token->n_args, OP_EQ, 2);
    417  tt_str_op(token->args[0], OP_EQ,
    418                  "0232AF901C31A04EE9848595AF9BB7620D4C5B2E");
    419  tt_str_op(token->args[1], OP_EQ,
    420                  "CD1FD971855430880D3C31E0331C5C55800C2F79");
    421 
    422  tt_assert(!token->error);
    423 
    424  char decoded[256];
    425  const char *signature =
    426    "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n"
    427    "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n"
    428    "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n"
    429    "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n"
    430    "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n"
    431    "Ua9DEZB9KbJHVX1rGShrLA==\n";
    432  tt_assert(signature);
    433  size_t signature_len = strlen(signature);
    434  base64_decode(decoded, sizeof(decoded), signature, signature_len);
    435 
    436  tt_str_op(token->object_type, OP_EQ, "SIGNATURE");
    437  tt_int_op(token->object_size, OP_EQ, 256);
    438  tt_mem_op(token->object_body, OP_EQ, decoded, 256);
    439 
    440  tt_assert(!token->key);
    441 
    442 done:
    443  memarea_drop_all(area);
    444 }
    445 
    446 static void
    447 test_parsecommon_get_next_token_err_too_many_args(void *arg)
    448 {
    449  memarea_t *area = memarea_new();
    450  const char *str = "uptime 1024 1024 1024";
    451  const char *end = str + strlen(str);
    452  const char **s = &str;
    453  token_rule_t table = T01("uptime", K_UPTIME, EQ(1), NO_OBJ);
    454  (void)arg;
    455 
    456  directory_token_t *token = get_next_token(area, s, end, &table);
    457 
    458  tt_int_op(token->tp, OP_EQ, ERR_);
    459  tt_str_op(token->error, OP_EQ, "Too many arguments to uptime");
    460 
    461 done:
    462  memarea_drop_all(area);
    463  return;
    464 }
    465 
    466 static void
    467 test_parsecommon_get_next_token_err_too_few_args(void *arg)
    468 {
    469  memarea_t *area = memarea_new();
    470  const char *str = "uptime";
    471  const char *end = str + strlen(str);
    472  const char **s = &str;
    473  token_rule_t table = T01("uptime", K_UPTIME, EQ(1), NO_OBJ);
    474  (void)arg;
    475 
    476  directory_token_t *token = get_next_token(area, s, end, &table);
    477 
    478  tt_int_op(token->tp, OP_EQ, ERR_);
    479  tt_str_op(token->error, OP_EQ, "Too few arguments to uptime");
    480 
    481 done:
    482  memarea_drop_all(area);
    483  return;
    484 }
    485 
    486 static void
    487 test_parsecommon_get_next_token_err_obj_missing_endline(void *arg)
    488 {
    489  memarea_t *area = memarea_new();
    490 
    491  const char *str =
    492    "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E "
    493    "CD1FD971855430880D3C31E0331C5C55800C2F79\n"
    494    "-----BEGIN SIGNATURE-----\n"
    495    "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n"
    496    "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n"
    497    "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n"
    498    "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n"
    499    "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n"
    500    "Ua9DEZB9KbJHVX1rGShrLA==\n";
    501 
    502  const char *end = str + strlen(str);
    503  const char **s = &str;
    504  token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE,
    505                        GE(2), NEED_OBJ);
    506  (void)arg;
    507 
    508  directory_token_t *token = get_next_token(area, s, end, &rule);
    509 
    510  tt_int_op(token->tp, OP_EQ, ERR_);
    511  tt_str_op(token->error, OP_EQ, "Malformed object: missing object end line");
    512 
    513 done:
    514  memarea_drop_all(area);
    515  return;
    516 }
    517 
    518 static void
    519 test_parsecommon_get_next_token_err_bad_beginline(void *arg)
    520 {
    521  memarea_t *area = memarea_new();
    522 
    523  const char *str =
    524    "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E "
    525    "CD1FD971855430880D3C31E0331C5C55800C2F79\n"
    526    "-----BEGIN SIGNATURE-Z---\n"
    527    "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n"
    528    "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n"
    529    "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n"
    530    "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n"
    531    "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n"
    532    "Ua9DEZB9KbJHVX1rGShrLA==\n"
    533    "-----END SIGNATURE-----\n";
    534 
    535  const char *end = str + strlen(str);
    536  const char **s = &str;
    537  token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE,
    538                        GE(2), NEED_OBJ);
    539  (void)arg;
    540 
    541  directory_token_t *token = get_next_token(area, s, end, &rule);
    542 
    543  tt_int_op(token->tp, OP_EQ, ERR_);
    544  tt_str_op(token->error, OP_EQ, "Malformed object: bad begin line");
    545 
    546 done:
    547  memarea_drop_all(area);
    548  return;
    549 }
    550 
    551 static void
    552 test_parsecommon_get_next_token_err_tag_mismatch(void *arg)
    553 {
    554  memarea_t *area = memarea_new();
    555 
    556  const char *str =
    557    "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E "
    558    "CD1FD971855430880D3C31E0331C5C55800C2F79\n"
    559    "-----BEGIN SIGNATURE-----\n"
    560    "dLTbc1Lad/OWKBJhA/dERzDHumswTAzBFAWAz2vnQhLsebs1SOm0W/vceEsiEkiF\n"
    561    "A+JJSzIyfywJc6Mnk7aKMEIFjOO/MaxuAp4zv+q+JonJkF0ExjMqvKR0D6pSFmfN\n"
    562    "cnemnxGHxNuPDnKl0imbWKmWDsHtwgi4zWeTq3MekfMOXKi6gIh+bDFzCs9/Vquh\n"
    563    "uNKJI1jW/A2DEKeaSAODEv9VoCsYSvbVVEuHCBWjeNAurd5aL26BrAolW6m7pkD6\n"
    564    "I+cQ8dQG6Wa/Zt6gLXtBbOP2o/iDI7ahDP9diNkBI/rm4nfp9j4piTwsqpi7xz9J\n"
    565    "Ua9DEZB9KbJHVX1rGShrLA==\n"
    566    "-----END SOMETHINGELSE-----\n";
    567 
    568  const char *end = str + strlen(str);
    569  const char **s = &str;
    570  token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE,
    571                        GE(2), NEED_OBJ);
    572  (void)arg;
    573 
    574  directory_token_t *token = get_next_token(area, s, end, &rule);
    575 
    576  tt_int_op(token->tp, OP_EQ, ERR_);
    577  tt_str_op(token->error, OP_EQ,
    578            "Malformed object: mismatched end tag SIGNATURE");
    579 
    580 done:
    581  memarea_drop_all(area);
    582  return;
    583 }
    584 
    585 static void
    586 test_parsecommon_get_next_token_err_bad_base64(void *arg)
    587 {
    588  memarea_t *area = memarea_new();
    589 
    590  const char *str =
    591    "directory-signature 0232AF901C31A04EE9848595AF9BB7620D4C5B2E "
    592    "CD1FD971855430880D3C31E0331C5C55800C2F79\n"
    593    "-----BEGIN SIGNATURE-----\n"
    594    "%%@%%%%%%%!!!'\n"
    595    "-----END SIGNATURE-----\n";
    596 
    597  const char *end = str + strlen(str);
    598  const char **s = &str;
    599  token_rule_t rule = T("directory-signature", K_DIRECTORY_SIGNATURE,
    600                        GE(2), NEED_OBJ);
    601  (void)arg;
    602 
    603  directory_token_t *token = get_next_token(area, s, end, &rule);
    604 
    605  tt_int_op(token->tp, OP_EQ, ERR_);
    606  tt_str_op(token->error, OP_EQ, "Malformed object: bad base64-encoded data");
    607 
    608 done:
    609  memarea_drop_all(area);
    610  return;
    611 }
    612 
    613 #define PARSECOMMON_TEST(name) \
    614  { #name, test_parsecommon_ ## name, 0, NULL, NULL }
    615 
    616 struct testcase_t parsecommon_tests[] = {
    617  PARSECOMMON_TEST(tokenize_string_null),
    618  PARSECOMMON_TEST(get_next_token_carriage_return),
    619  PARSECOMMON_TEST(tokenize_string_multiple_lines),
    620  PARSECOMMON_TEST(tokenize_string_min_cnt),
    621  PARSECOMMON_TEST(tokenize_string_max_cnt),
    622  PARSECOMMON_TEST(tokenize_string_at_start),
    623  PARSECOMMON_TEST(tokenize_string_at_end),
    624  PARSECOMMON_TEST(tokenize_string_no_annotations),
    625  PARSECOMMON_TEST(get_next_token_success),
    626  PARSECOMMON_TEST(get_next_token_concat_args),
    627  PARSECOMMON_TEST(get_next_token_parse_keys),
    628  PARSECOMMON_TEST(get_next_token_object),
    629  PARSECOMMON_TEST(get_next_token_err_too_many_args),
    630  PARSECOMMON_TEST(get_next_token_err_too_few_args),
    631  PARSECOMMON_TEST(get_next_token_err_obj_missing_endline),
    632  PARSECOMMON_TEST(get_next_token_err_bad_beginline),
    633  PARSECOMMON_TEST(get_next_token_err_tag_mismatch),
    634  PARSECOMMON_TEST(get_next_token_err_bad_base64),
    635  END_OF_TESTCASES
    636 };