diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-07-10 20:18:28 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-07-10 20:18:28 -0400 |
commit | 537092cdbb7f4be0e6d68f4e5d65ca2a403375f9 (patch) | |
tree | 71b283d62b9babf05d38bc105f3f623e2c564b63 /src | |
parent | c08b7b10c520db08e20e6ac5630f0a668d5ecf3a (diff) | |
parent | c90961a9233e7287605886585503ee94d13a4592 (diff) | |
download | tor-537092cdbb7f4be0e6d68f4e5d65ca2a403375f9.tar.gz tor-537092cdbb7f4be0e6d68f4e5d65ca2a403375f9.zip |
Merge branch 'ticket26223'
Diffstat (limited to 'src')
-rw-r--r-- | src/ext/getdelim.c | 78 | ||||
-rw-r--r-- | src/ext/include.am | 2 | ||||
-rw-r--r-- | src/feature/dircache/dirserv.c | 35 | ||||
-rw-r--r-- | src/lib/fs/.may_include | 3 | ||||
-rw-r--r-- | src/lib/fs/files.c | 4 | ||||
-rw-r--r-- | src/lib/fs/files.h | 39 |
6 files changed, 145 insertions, 16 deletions
diff --git a/src/ext/getdelim.c b/src/ext/getdelim.c new file mode 100644 index 0000000000..8254103ff9 --- /dev/null +++ b/src/ext/getdelim.c @@ -0,0 +1,78 @@ +/* $NetBSD: getdelim.c,v 1.2 2015/12/25 20:12:46 joerg Exp $ */ +/* NetBSD-src: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BUFSIZ +#define BUFSIZ 512 +#endif + +ssize_t +compat_getdelim_(char **buf, size_t *bufsiz, int delimiter, FILE *fp) +{ + char *ptr, *eptr; + + + if (*buf == NULL || *bufsiz == 0) { + *bufsiz = BUFSIZ; + if ((*buf = raw_malloc(*bufsiz)) == NULL) + return -1; + } + + for (ptr = *buf, eptr = *buf + *bufsiz;;) { + int c = fgetc(fp); + if (c == -1) { + if (feof(fp)) { + ssize_t diff = (ssize_t)(ptr - *buf); + if (diff != 0) { + *ptr = '\0'; + return diff; + } + } + return -1; + } + *ptr++ = c; + if (c == delimiter) { + *ptr = '\0'; + return ptr - *buf; + } + if (ptr + 2 >= eptr) { + char *nbuf; + size_t nbufsiz = *bufsiz * 2; + ssize_t d = ptr - *buf; + if ((nbuf = raw_realloc(*buf, nbufsiz)) == NULL) + return -1; + *buf = nbuf; + *bufsiz = nbufsiz; + eptr = nbuf + nbufsiz; + ptr = nbuf + d; + } + } +} diff --git a/src/ext/include.am b/src/ext/include.am index 7ec2e43312..6bdce2d79e 100644 --- a/src/ext/include.am +++ b/src/ext/include.am @@ -10,6 +10,7 @@ EXTHEADERS = \ src/ext/tor_readpassphrase.h \ src/ext/strlcat.c \ src/ext/strlcpy.c \ + src/ext/getdelim.c \ src/ext/tinytest_macros.h \ src/ext/tor_queue.h \ src/ext/siphash.h \ @@ -173,4 +174,3 @@ EXTRA_DIST += \ src/ext/timeouts/Makefile \ src/ext/timeouts/Rules.shrc \ src/ext/timeouts/test-timeout.c - diff --git a/src/feature/dircache/dirserv.c b/src/feature/dircache/dirserv.c index c5286b0cbf..1500467ec0 100644 --- a/src/feature/dircache/dirserv.c +++ b/src/feature/dircache/dirserv.c @@ -2606,7 +2606,6 @@ int dirserv_read_measured_bandwidths(const char *from_file, smartlist_t *routerstatuses) { - char line[512]; FILE *fp = tor_fopen_cloexec(from_file, "r"); int applied_lines = 0; time_t file_time, now; @@ -2616,28 +2615,28 @@ dirserv_read_measured_bandwidths(const char *from_file, * if there are additional header lines, as introduced in Bandwidth List spec * version 1.1.0 */ int line_is_after_headers = 0; + int rv = -1; + char *line = NULL; + size_t n = 0; /* Initialise line, so that we can't possibly run off the end. */ - memset(line, 0, sizeof(line)); if (fp == NULL) { log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s", from_file); - return -1; + goto err; } /* If fgets fails, line is either unmodified, or indeterminate. */ - if (!fgets(line, sizeof(line), fp)) { + if (tor_getline(&line,&n,fp) <= 0) { log_warn(LD_DIRSERV, "Empty bandwidth file"); - fclose(fp); - return -1; + goto err; } if (!strlen(line) || line[strlen(line)-1] != '\n') { log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s", escaped(line)); - fclose(fp); - return -1; + goto err; } line[strlen(line)-1] = '\0'; @@ -2645,16 +2644,14 @@ dirserv_read_measured_bandwidths(const char *from_file, if (!ok) { log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s", escaped(line)); - fclose(fp); - return -1; + goto err; } now = time(NULL); if ((now - file_time) > MAX_MEASUREMENT_AGE) { log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u", (unsigned)(time(NULL) - file_time)); - fclose(fp); - return -1; + goto err; } if (routerstatuses) @@ -2662,7 +2659,7 @@ dirserv_read_measured_bandwidths(const char *from_file, while (!feof(fp)) { measured_bw_line_t parsed_line; - if (fgets(line, sizeof(line), fp) && strlen(line)) { + if (tor_getline(&line, &n, fp) >= 0) { if (measured_bw_line_parse(&parsed_line, line, line_is_after_headers) != -1) { /* This condition will be true when the first complete valid bw line @@ -2679,11 +2676,19 @@ dirserv_read_measured_bandwidths(const char *from_file, /* Now would be a nice time to clean the cache, too */ dirserv_expire_measured_bw_cache(now); - fclose(fp); log_info(LD_DIRSERV, "Bandwidth measurement file successfully read. " "Applied %d measurements.", applied_lines); - return 0; + rv = 0; + + err: + if (line) { + // we need to raw_free this buffer because we got it from tor_getdelim() + raw_free(line); + } + if (fp) + fclose(fp); + return rv; } /** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t diff --git a/src/lib/fs/.may_include b/src/lib/fs/.may_include index 6c9ce6ca04..b1e49fc891 100644 --- a/src/lib/fs/.may_include +++ b/src/lib/fs/.may_include @@ -1,4 +1,7 @@ orconfig.h + +ext/getdelim.c + lib/cc/*.h lib/container/*.h lib/encoding/*.h diff --git a/src/lib/fs/files.c b/src/lib/fs/files.c index c71e4d2a37..43dcbad333 100644 --- a/src/lib/fs/files.c +++ b/src/lib/fs/files.c @@ -715,3 +715,7 @@ read_file_to_str, (const char *filename, int flags, struct stat *stat_out)) return string; } + +#if !defined(HAVE_GETDELIM) || defined(TOR_UNIT_TESTS) +#include "ext/getdelim.c" +#endif diff --git a/src/lib/fs/files.h b/src/lib/fs/files.h index 5a12eb8215..2ee1b20149 100644 --- a/src/lib/fs/files.h +++ b/src/lib/fs/files.h @@ -103,4 +103,43 @@ char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out) ATTR_MALLOC; +#if !defined(HAVE_GETDELIM) || defined(TOR_UNIT_TESTS) +/** Internal back-end function to implement getdelim(): only exists when + * Tor is built for unit tests, or when Tor is built on an operating system + * without its own getdelim(). */ +ssize_t compat_getdelim_(char **lineptr, size_t *n, int delim, FILE *stream); +#endif + +#ifdef HAVE_GETDELIM +/** + * Cross-platform wrapper for getdelim(): behaves as the POSIX-standard + * getdelim() function. + * + * See `getdelim(3)` for more information. + * + * Note that this function will use the libc memory allocator -- so any memory + * passed to this function must come from raw_malloc(), and must be freed by + * raw_free() -- don't use tor_malloc() and tor_free() with this. + */ +#define tor_getdelim(lineptr, n, delim, stream) \ + getdelim((lineptr), (n), (delim), (stream)) +#else +#define tor_getdelim(lineptr, n, delim, stream) \ + compat_getdelim_((lineptr), (n), (delim), (stream)) +#endif + +#ifdef HAVE_GETLINE +/** + * Cross-platform wrapper for getline(): behaves as the POSIX-standard + * getline() function. + * + * See tor_getdelim() for usage notes. + */ +#define tor_getline(lineptr, n, stream) \ + getline((lineptr), (n), (stream)) +#else +#define tor_getline(lineptr, n, stream) \ + tor_getdelim((lineptr), (n), '\n', (stream)) +#endif + #endif |