aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-07-10 20:18:28 -0400
committerNick Mathewson <nickm@torproject.org>2018-07-10 20:18:28 -0400
commit537092cdbb7f4be0e6d68f4e5d65ca2a403375f9 (patch)
tree71b283d62b9babf05d38bc105f3f623e2c564b63 /src
parentc08b7b10c520db08e20e6ac5630f0a668d5ecf3a (diff)
parentc90961a9233e7287605886585503ee94d13a4592 (diff)
downloadtor-537092cdbb7f4be0e6d68f4e5d65ca2a403375f9.tar.gz
tor-537092cdbb7f4be0e6d68f4e5d65ca2a403375f9.zip
Merge branch 'ticket26223'
Diffstat (limited to 'src')
-rw-r--r--src/ext/getdelim.c78
-rw-r--r--src/ext/include.am2
-rw-r--r--src/feature/dircache/dirserv.c35
-rw-r--r--src/lib/fs/.may_include3
-rw-r--r--src/lib/fs/files.c4
-rw-r--r--src/lib/fs/files.h39
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