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

Ticket3723 02 #194

Closed
wants to merge 14 commits into from
Closed

Ticket3723 02 #194

wants to merge 14 commits into from

Conversation

juga0
Copy link
Contributor

@juga0 juga0 commented Jun 30, 2018

Follows #126 after rebase to master.
@teor2345 I think i addressed all your comments.
In the end i thought it was better to add all the tests to the same function to don't duplicate all the variables.
Instead of truncating the string with the bandwidth file headers, i thought it was better to truncate the smartlist. I created a function for that but something is wrong since there's memory leaks when i use it in the test. See the last 3 commits and the FIXMEs in the code. Not ready to merge because of that.

juga0 added 13 commits June 28, 2018 19:53
* add bwlist_headers argument to dirserv_read_measured_bandwidth
  in order to store all the headers found when parsing the file
* add bwlist_headers to networkstatus_t in order to store the
  the headers found by the previous function
* include the bandwidth headers as string in vote documents
* add test to check that dirserv_read_measured_bandwidth generates
  the bwlist_headers
when there are not bw file headers lines.
to avoid interpreting as headers extra lines that are not key_values
and add bw file terminator constant
If bandwidth file terminator is found, set end of headers flag
and do not store the line.
If it is not, parse a relay line and check whether it is a header
line.
also add tests for bw_file_headers.
Headers are all that is found before a correct relay line or
the terminator.
Tests include:
* a empty bandwidth file
* a bandwidth file with only timestamp
* a bandwidth file with v1.0.0 headers
* a bandwidth file with v1.0.0 headers and relay lines
* a bandwidth file with v1.1.0 headers and v1.0.0 relay lines
* a bandwidth file with v1.0.0 headers, malformed relay lines and
  relay lines
* a bandwidth file with v1.0.0 headers, malformed relay lines,
  relay lines and malformed relay lines
* a bandwidth file with v1.1.0 headers without terminator
* a bandwidth file with v1.1.0 headers with terminator
* a bandwidth file with v1.1.0 headers without terminator and
  relay lines
* a bandwidth file with v1.1.0 headers with terminator and relay
  lines
* a bandwidth file with v1.1.0 headers without terminator, bad
  relay lines and relay lines
* a bandwidth file with v1.1.0 headers with terminator, bad relay
  lines and relay lines
and complete v1.0.0 bandwidth file
FIXME: this seems to leak memory
FIXME: depends on smartlist_truncate
@juga0 juga0 mentioned this pull request Jun 30, 2018
@juga0
Copy link
Contributor Author

juga0 commented Jun 30, 2018

Right now there is also this problem with last fixup:

src/or/dirserv.c:2690:15: error: implicit declaration of function ‘string_is_key_value’ [-Werror=implicit-function-declaration]
               string_is_key_value(LOG_DEBUG, line) &&
               ^
src/or/dirserv.c:2690:15: error: nested extern declaration of ‘string_is_key_value’ [-Werror=nested-externs]

Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

Please see my comments on the new code.


/** Terminatore that separates bandwidth file headers from bandwidth file
* relay lines */
#define BW_FILE_TERMINATOR "=====\n"
Copy link
Contributor

Choose a reason for hiding this comment

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

Please rename to BW_FILE_HEADERS_TERMINATOR to avoid confusion.

* then assume this line is a header and add it to bw_file_headers */
else if (bw_file_headers &&
(line_is_after_headers == 0) &&
string_is_key_value(LOG_DEBUG, line) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

string_is_key_value returns true for relay bandwidth lines, because it allows spaces:

string_is_key_value(int severity, const char *string)

Please also check that there are no spaces in the line.

for (i=0; i < diff; i++) {
log_debug(LD_DIRSERV, "sl->list[size] %s\n", (char *)sl->list[size]);
log_debug(LD_DIRSERV, "sl len %d\n", smartlist_len(sl));
smartlist_del(sl, size);
Copy link
Contributor

Choose a reason for hiding this comment

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

Use smartlist_del_keeporder() to avoid reordering the bandwidth headers.
Use smartlist_del_keeporder(sl, i) to delete the correct item.
Use tor_free(smartlist_get(sl, i)) to free the item before deleting it.

Also, you should probably delete from the end of the smartlist, rather than the start.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I think we can delete this entire commit.
See my comments on the next commit.

if (smartlist_len(v3_ns->bw_file_headers) > MAX_BW_FILE_HEADERS_LEN)
/* FIXME */
smartlist_truncate(v3_ns->bw_file_headers, MAX_BW_FILE_HEADERS_LEN);
} else
bw_file_headers = tor_strdup("");
Copy link
Contributor

Choose a reason for hiding this comment

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

If any block in a group of if/else blocks has braces, please put braces around every block.

NULL);
if (smartlist_len(v3_ns->bw_file_headers) > MAX_BW_FILE_HEADERS_LEN)
/* FIXME */
smartlist_truncate(v3_ns->bw_file_headers, MAX_BW_FILE_HEADERS_LEN);
Copy link
Contributor

Choose a reason for hiding this comment

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

We already limit the number of headers in earlier code.

So you can just log a BUG() warning here, and vote an empty string:

if (BUG(smartlist_len(v3_ns->bw_file_headers) > MAX_BW_FILE_HEADERS_LEN)) {
    bw_file_headers = tor_strdup("");
}

You should do this check before joining the string together, to avoid a memory leak, and to avoid allocating large amounts of memory.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so then i would do 2 checks?, 1 with the smartlist and 1 with the string?.
The code then would be:

      if (BUG(smartlist_len(v3_ns->bw_file_headers) > MAX_BW_FILE_HEADERS_LEN)) {
        bw_file_headers = tor_strdup("");
      }
      bw_file_headers = smartlist_join_strings(v3_ns->bw_file_headers, " ", 0,
                                               NULL);
      if (BUG(strlen(bw_file_headers) > MAX_VOTE_LINE_LEN)) {
        tor_free(bw_file_headers);
        bw_file_headers = tor_strdup("");
      }

Copy link
Contributor

Choose a reason for hiding this comment

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

Almost, but you can't overwrite bw_file_headers with valid data after an error:

      if (BUG(smartlist_len(v3_ns->bw_file_headers) > MAX_BW_FILE_HEADERS_LEN)) {
        bw_file_headers = tor_strdup("");
      } else {
        bw_file_headers = smartlist_join_strings(v3_ns->bw_file_headers, " ", 0,
                                                 NULL);
        if (BUG(strlen(bw_file_headers) > MAX_VOTE_LINE_LEN)) {
          tor_free(bw_file_headers);
          bw_file_headers = tor_strdup("");
        }
    }

Here's another alternative that might make the code simpler:

      char *bw_file_headers = NULL;
      …
      if (! BUG(smartlist_len(v3_ns->bw_file_headers) > MAX_BW_FILE_HEADERS_LEN)) {
        bw_file_headers = smartlist_join_strings(v3_ns->bw_file_headers, " ", 0,
                                                 NULL);
        if (BUG(strlen(bw_file_headers) > MAX_VOTE_LINE_LEN)) {
          /* Free and set to NULL, so the vote header line is empty */
          tor_free(bw_file_headers);
        }
      }
      …
      bw_file_headers ? bw_file_headers : "");

Then the final tor_free(bw_file_headers) works because free(NULL) does nothing.

@@ -267,10 +267,13 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
else
params = tor_strdup("");
tor_assert(cert);
if (v3_ns->bw_file_headers)
if (v3_ns->bw_file_headers) {
bw_file_headers = smartlist_join_strings(v3_ns->bw_file_headers, " ", 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

Please limit the length of the bw_file_headers string, not just the number of headers:
#126 (comment)

(Limiting the number of headers to 50 header is not enough to limit the vote line to 1024 bytes, because each header can be 512 bytes long.)

Copy link
Contributor

Choose a reason for hiding this comment

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

You could log a BUG() warning and use the empty string if the string is too long.
(It's very unlikely that the string will be too long.)
Remember to free the string before replacing it with "".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(Limiting the number of headers to 50 header is not enough to limit the vote line to 1024 bytes, because each header can be 512 bytes long.)

Is there already a constant limiting the size of the vote line?, i don't find something like that, maybe i should add it?.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It would be:

/** Maximum size of a line in a vote. */
MAX_VOTE_LINE_LEN 1024

In dirvote.h

Copy link
Contributor

Choose a reason for hiding this comment

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

There are similar line length constants in diserv.h:
https://github.com/torproject/tor/blob/master/src/or/dirserv.h#L29
So I think this new constant should go in dirserv.h, even though it's only used in votes.

You said:

/** Maximum size of a line in a vote. */
MAX_VOTE_LINE_LEN 1024
But this constant does not limit all lines in the vote, just the bandwidth-file-headers line.

Please name the line limit constant after the kind of line, something like:
MAX_BANDWIDTH_HEADERS_LINE_LEN

Copy link
Contributor

Choose a reason for hiding this comment

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

Or MAX_BW_FILE_HEADERS_LINE_LEN to match MAX_BW_FILE_HEADERS_LEN.

Copy link
Contributor

Choose a reason for hiding this comment

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

Now that we have two similar constants, we should change MAX_BW_FILE_HEADERS_LEN to MAX_BW_FILE_HEADER_COUNT_IN_VOTE. Otherwise people might get confused.

@teor2345
Copy link
Contributor

Right now there is also this problem with last fixup:

key_value.h isn't included in util.h:
https://github.com/torproject/tor/blob/master/src/common/util.h#L19

Please make a separate commit with this fix.

@juga0 juga0 mentioned this pull request Jul 1, 2018
@juga0 juga0 closed this Jul 1, 2018
@juga0
Copy link
Contributor Author

juga0 commented Jul 1, 2018

Continuing in #195

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants