diff options
Diffstat (limited to 'src/journal-remote/journal-remote-parse.c')
-rw-r--r-- | src/journal-remote/journal-remote-parse.c | 73 |
1 files changed, 40 insertions, 33 deletions
diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c index dbdf02aa3c..fe21bd3e1d 100644 --- a/src/journal-remote/journal-remote-parse.c +++ b/src/journal-remote/journal-remote-parse.c @@ -49,43 +49,43 @@ static int get_line(RemoteSource *source, char **line, size_t *size) { assert(source->filled <= source->size); assert(source->buf == NULL || source->size > 0); - if (source->buf) - c = memchr(source->buf, '\n', source->filled); - - if (c != NULL) - goto docopy; - - resize: - if (source->fd < 0) - /* we have to wait for some data to come to us */ - return -EWOULDBLOCK; + while (true) { + if (source->buf) + c = memchr(source->buf + source->scanned, '\n', + source->filled - source->scanned); + if (c != NULL) + break; + + source->scanned = source->filled; + if (source->scanned >= DATA_SIZE_MAX) { + log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX); + return -E2BIG; + } - if (source->size - source->filled < LINE_CHUNK) { - // XXX: add check for maximum line length + if (source->fd < 0) + /* we have to wait for some data to come to us */ + return -EWOULDBLOCK; - if (!GREEDY_REALLOC(source->buf, source->size, - source->filled + LINE_CHUNK)) - return log_oom(); - } - assert(source->size - source->filled >= LINE_CHUNK); + if (source->size - source->filled < LINE_CHUNK && + !GREEDY_REALLOC(source->buf, source->size, + MAX(source->filled + LINE_CHUNK, DATA_SIZE_MAX))) + return log_oom(); - n = read(source->fd, source->buf + source->filled, - source->size - source->filled); - if (n < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) - log_error("read(%d, ..., %zd): %m", source->fd, - source->size - source->filled); - return -errno; - } else if (n == 0) - return 0; + assert(source->size - source->filled >= LINE_CHUNK); - c = memchr(source->buf + source->filled, '\n', n); - source->filled += n; + n = read(source->fd, source->buf + source->filled, + MAX(source->size, DATA_SIZE_MAX) - source->filled); + if (n < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) + log_error("read(%d, ..., %zd): %m", source->fd, + source->size - source->filled); + return -errno; + } else if (n == 0) + return 0; - if (c == NULL) - goto resize; + source->filled += n; + } - docopy: *line = source->buf; *size = c + 1 - source->buf; @@ -102,6 +102,7 @@ static int get_line(RemoteSource *source, char **line, size_t *size) { source->buf = newbuf; source->size = newsize; source->filled = remain; + source->scanned = 0; return 1; } @@ -111,8 +112,12 @@ int push_data(RemoteSource *source, const char *data, size_t size) { assert(source->state != STATE_EOF); if (!GREEDY_REALLOC(source->buf, source->size, - source->filled + size)) - return log_oom(); + source->filled + size)) { + log_error("Failed to store received data of size %zu " + "(in addition to existing %zu bytes with %zu filled): %s", + size, source->size, source->filled, strerror(ENOMEM)); + return -ENOMEM; + } memcpy(source->buf + source->filled, data, size); source->filled += size; @@ -131,6 +136,7 @@ static int fill_fixed_size(RemoteSource *source, void **data, size_t size) { source->state == STATE_DATA_FINISH); assert(size <= DATA_SIZE_MAX); assert(source->filled <= source->size); + assert(source->scanned <= source->filled); assert(source->buf != NULL || source->size == 0); assert(source->buf == NULL || source->size > 0); assert(data); @@ -171,6 +177,7 @@ static int fill_fixed_size(RemoteSource *source, void **data, size_t size) { source->buf = newbuf; source->size = newsize; source->filled = remain; + source->scanned = 0; return 1; } |