commit ec368409fa7732a08e85c1bfb254469f02458266 Author: Nick Mathewson nickm@torproject.org Date: Mon Sep 9 15:41:24 2019 -0400
Extract field-parsing code for microdesc_parse.c
The code here parses the fields from the microdescriptor, including possible annotations, and stores them into a microdesc_t object.
This commit is almost pure code movement; I recommend using --color-moved to review it. --- src/feature/dirparse/microdesc_parse.c | 143 +++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 60 deletions(-)
diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c index 29bebbed3..5af4c60cb 100644 --- a/src/feature/dirparse/microdesc_parse.c +++ b/src/feature/dirparse/microdesc_parse.c @@ -162,62 +162,27 @@ microdesc_extract_body(microdesc_t *md, return no_onion_key ? -1 : 0; }
-/** Parse as many microdescriptors as are found from the string starting at - * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any - * annotations we recognize and ignore ones we don't. - * - * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each - * descriptor in the body field of each microdesc_t. +/** + * Parse a microdescriptor which begins at <b>s</b> and ends at + * <b>start_of_next_microdesc. Store its fields into <b>md</b>. Use + * <b>where</b> for generating log information. If <b>allow_annotations</b> + * is true, then one or more annotations may precede the microdescriptor body + * proper. Use <b>area</b> for memory management, clearing it when done. * - * Return all newly parsed microdescriptors in a newly allocated - * smartlist_t. If <b>invalid_disgests_out</b> is provided, add a SHA256 - * microdesc digest to it for every microdesc that we found to be badly - * formed. (This may cause duplicates) */ -smartlist_t * -microdescs_parse_from_string(const char *s, const char *eos, - int allow_annotations, - saved_location_t where, - smartlist_t *invalid_digests_out) + * On success, return 0; otherwise return -1. + **/ +static int +microdesc_parse_fields(microdesc_t *md, + memarea_t *area, + const char *s, const char *start_of_next_microdesc, + int allow_annotations, + saved_location_t where) { - smartlist_t *tokens; - smartlist_t *result; - microdesc_t *md = NULL; - memarea_t *area; - const char *start = s; - const char *start_of_next_microdesc; + smartlist_t *tokens = smartlist_new(); + int rv = -1; int flags = allow_annotations ? TS_ANNOTATIONS_OK : 0; - directory_token_t *tok;
- if (!eos) - eos = s + strlen(s); - - s = eat_whitespace_eos(s, eos); - area = memarea_new(); - result = smartlist_new(); - tokens = smartlist_new(); - - while (s < eos) { - int okay = 0; - - start_of_next_microdesc = find_start_of_next_microdesc(s, eos); - if (!start_of_next_microdesc) - start_of_next_microdesc = eos; - - md = tor_malloc_zero(sizeof(microdesc_t)); - uint8_t md_digest[DIGEST256_LEN]; - { - int body_not_found = microdesc_extract_body(md, start, s, - start_of_next_microdesc, - where) < 0; - - memcpy(md_digest, md->digest, DIGEST256_LEN); - if (body_not_found) { - log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Malformed or truncated descriptor"); - goto next; - } - } - if (tokenize_string(area, s, start_of_next_microdesc, tokens, microdesc_token_table, flags)) { log_warn(LD_DIR, "Unparseable microdescriptor found in %s", @@ -301,10 +266,74 @@ microdescs_parse_from_string(const char *s, const char *eos, md->policy_is_reject_star = 1; }
- smartlist_add(result, md); - okay = 1; + rv = 0; + next: // todo: rename this label. + + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); + memarea_clear(area); + smartlist_free(tokens); + + return rv; +} + +/** Parse as many microdescriptors as are found from the string starting at + * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any + * annotations we recognize and ignore ones we don't. + * + * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each + * descriptor in the body field of each microdesc_t. + * + * Return all newly parsed microdescriptors in a newly allocated + * smartlist_t. If <b>invalid_disgests_out</b> is provided, add a SHA256 + * microdesc digest to it for every microdesc that we found to be badly + * formed. (This may cause duplicates) */ +smartlist_t * +microdescs_parse_from_string(const char *s, const char *eos, + int allow_annotations, + saved_location_t where, + smartlist_t *invalid_digests_out) +{ + smartlist_t *result; + microdesc_t *md = NULL; + memarea_t *area; + const char *start = s; + const char *start_of_next_microdesc; + + if (!eos) + eos = s + strlen(s); + + s = eat_whitespace_eos(s, eos); + area = memarea_new(); + result = smartlist_new(); + + while (s < eos) { + int okay = 0; + + start_of_next_microdesc = find_start_of_next_microdesc(s, eos); + if (!start_of_next_microdesc) + start_of_next_microdesc = eos; + + md = tor_malloc_zero(sizeof(microdesc_t)); + uint8_t md_digest[DIGEST256_LEN]; + { + int body_not_found = microdesc_extract_body(md, start, s, + start_of_next_microdesc, + where) < 0; + + memcpy(md_digest, md->digest, DIGEST256_LEN); + if (body_not_found) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Malformed or truncated descriptor"); + goto next; + } + } + + if (microdesc_parse_fields(md, area, s, start_of_next_microdesc, + allow_annotations, where) == 0) { + smartlist_add(result, md); + md = NULL; // prevent free + okay = 1; + }
- md = NULL; next: if (! okay && invalid_digests_out) { smartlist_add(invalid_digests_out, @@ -312,16 +341,10 @@ microdescs_parse_from_string(const char *s, const char *eos, } microdesc_free(md); md = NULL; - - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); - memarea_clear(area); - smartlist_clear(tokens); s = start_of_next_microdesc; }
- SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); memarea_drop_all(area); - smartlist_free(tokens);
return result; }
tor-commits@lists.torproject.org