Merge pull request #9014 from keszybz/fuzz-journal-remote

A fuzzer for journal-remote
This commit is contained in:
Lennart Poettering 2018-05-31 15:33:44 +02:00 committed by GitHub
commit 89544ae658
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 1882 additions and 1351 deletions

View file

@ -116,9 +116,11 @@
<refsect1>
<title>Return Value</title>
<para>The two calls return 0 on success (in which case
<parameter>ret</parameter> is filled in), or a negative
errno-style error code.</para>
<para>Those calls return 0 on success (in which case <parameter>ret</parameter> is filled in),
or a negative errno-style error code. In particular, <function>sd_id128_get_machine()</function>
and <function>sd_id128_get_machine_app_specific()</function> return <constant>-ENOENT</constant>
if <filename>/etc/machine-id</filename> is missing, and <constant>-ENOMEDIUM</constant> if is
empty or all zeros.</para>
</refsect1>
<refsect1>

View file

@ -1258,6 +1258,7 @@ includes = include_directories('src/basic',
'src/shared',
'src/systemd',
'src/journal',
'src/journal-remote',
'src/nspawn',
'src/resolve',
'src/timesync',
@ -2007,7 +2008,8 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1
s_j_remote = executable('systemd-journal-remote',
systemd_journal_remote_sources,
include_directories : includes,
link_with : [libshared],
link_with : [libshared,
libsystemd_journal_remote],
dependencies : [threads,
libmicrohttpd,
libgnutls,

View file

@ -15,8 +15,8 @@
#include "macro.h"
#include "utf8.h"
size_t cescape_char(char c, char *buf) {
char * buf_old = buf;
int cescape_char(char c, char *buf) {
char *buf_old = buf;
switch (c) {

View file

@ -45,7 +45,7 @@ typedef enum EscapeStyle {
char *cescape(const char *s);
char *cescape_length(const char *s, size_t n);
size_t cescape_char(char c, char *buf);
int cescape_char(char c, char *buf);
int cunescape(const char *s, UnescapeFlags flags, char **ret);
int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);

View file

@ -9,9 +9,12 @@
#include <unistd.h>
#include "alloc-util.h"
#include "escape.h"
#include "fd-util.h"
#include "io-util.h"
#include "journal-file.h"
#include "journal-importer.h"
#include "journal-util.h"
#include "parse-util.h"
#include "string-util.h"
#include "unaligned.h"
@ -232,56 +235,78 @@ static int get_data_newline(JournalImporter *imp) {
assert(data);
if (*data != '\n') {
log_error("expected newline, got '%c'", *data);
char buf[4];
int l;
l = cescape_char(*data, buf);
log_error("Expected newline, got '%.*s'", l, buf);
return -EINVAL;
}
return 1;
}
static int process_dunder(JournalImporter *imp, char *line, size_t n) {
const char *timestamp;
static int process_special_field(JournalImporter *imp, char *line) {
const char *value;
char buf[CELLESCAPE_DEFAULT_LENGTH];
int r;
assert(line);
assert(n > 0);
assert(line[n-1] == '\n');
/* XXX: is it worth to support timestamps in extended format?
* We don't produce them, but who knows... */
timestamp = startswith(line, "__CURSOR=");
if (timestamp)
value = startswith(line, "__CURSOR=");
if (value)
/* ignore __CURSOR */
return 1;
timestamp = startswith(line, "__REALTIME_TIMESTAMP=");
if (timestamp) {
long long unsigned x;
line[n-1] = '\0';
r = safe_atollu(timestamp, &x);
value = startswith(line, "__REALTIME_TIMESTAMP=");
if (value) {
uint64_t x;
r = safe_atou64(value, &x);
if (r < 0)
log_warning("Failed to parse __REALTIME_TIMESTAMP: '%s'", timestamp);
else
imp->ts.realtime = x;
return r < 0 ? r : 1;
return log_warning_errno(r, "Failed to parse __REALTIME_TIMESTAMP '%s': %m",
cellescape(buf, sizeof buf, value));
else if (!VALID_REALTIME(x)) {
log_warning("__REALTIME_TIMESTAMP out of range, ignoring: %"PRIu64, x);
return -ERANGE;
}
imp->ts.realtime = x;
return 1;
}
timestamp = startswith(line, "__MONOTONIC_TIMESTAMP=");
if (timestamp) {
long long unsigned x;
line[n-1] = '\0';
r = safe_atollu(timestamp, &x);
value = startswith(line, "__MONOTONIC_TIMESTAMP=");
if (value) {
uint64_t x;
r = safe_atou64(value, &x);
if (r < 0)
log_warning("Failed to parse __MONOTONIC_TIMESTAMP: '%s'", timestamp);
else
imp->ts.monotonic = x;
return r < 0 ? r : 1;
return log_warning_errno(r, "Failed to parse __MONOTONIC_TIMESTAMP '%s': %m",
cellescape(buf, sizeof buf, value));
else if (!VALID_MONOTONIC(x)) {
log_warning("__MONOTONIC_TIMESTAMP out of range, ignoring: %"PRIu64, x);
return -ERANGE;
}
imp->ts.monotonic = x;
return 1;
}
timestamp = startswith(line, "__");
if (timestamp) {
log_notice("Unknown dunder line %s", line);
/* Just a single underline, but it needs special treatment too. */
value = startswith(line, "_BOOT_ID=");
if (value) {
r = sd_id128_from_string(value, &imp->boot_id);
if (r < 0)
return log_warning_errno(r, "Failed to parse _BOOT_ID '%s': %m",
cellescape(buf, sizeof buf, value));
/* store the field in the usual fashion too */
return 0;
}
value = startswith(line, "__");
if (value) {
log_notice("Unknown dunder line __%s, ignoring.", cellescape(buf, sizeof buf, value));
return 1;
}
@ -314,10 +339,6 @@ int journal_importer_process_data(JournalImporter *imp) {
return 1;
}
r = process_dunder(imp, line, n);
if (r != 0)
return r < 0 ? r : 0;
/* MESSAGE=xxx\n
or
COREDUMP\n
@ -328,6 +349,21 @@ int journal_importer_process_data(JournalImporter *imp) {
/* chomp newline */
n--;
if (!journal_field_valid(line, sep - line, true)) {
char buf[64], *t;
t = strndupa(line, sep - line);
log_debug("Ignoring invalid field: \"%s\"",
cellescape(buf, sizeof buf, t));
return 0;
}
line[n] = '\0';
r = process_special_field(imp, line);
if (r != 0)
return r < 0 ? r : 0;
r = iovw_put(&imp->iovw, line, n);
if (r < 0)
return r;

View file

@ -11,6 +11,8 @@
#include <stdbool.h>
#include <sys/uio.h>
#include "sd-id128.h"
#include "time-util.h"
/* Make sure not to make this smaller than the maximum coredump size.
@ -45,6 +47,7 @@ typedef struct JournalImporter {
int state;
dual_timestamp ts;
sd_id128_t boot_id;
} JournalImporter;
void journal_importer_cleanup(JournalImporter *);

View file

@ -46,7 +46,7 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
* for us. */
/* Use the getrandom() syscall unless we know we don't have it. */
if (have_syscall != 0) {
if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
r = getrandom(p, n, GRND_NONBLOCK);
if (r > 0) {
have_syscall = true;

View file

@ -14,6 +14,7 @@
#include <string.h>
#include "alloc-util.h"
#include "escape.h"
#include "gunicode.h"
#include "locale-util.h"
#include "macro.h"
@ -453,6 +454,20 @@ bool string_has_cc(const char *p, const char *ok) {
return false;
}
static int write_ellipsis(char *buf, bool unicode) {
if (unicode || is_locale_utf8()) {
buf[0] = 0xe2; /* tri-dot ellipsis: … */
buf[1] = 0x80;
buf[2] = 0xa6;
} else {
buf[0] = '.';
buf[1] = '.';
buf[2] = '.';
}
return 3;
}
static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
size_t x, need_space;
char *r;
@ -501,17 +516,7 @@ static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_le
assert(x <= new_length - need_space);
memcpy(r, s, x);
if (is_locale_utf8()) {
r[x+0] = 0xe2; /* tri-dot ellipsis: … */
r[x+1] = 0x80;
r[x+2] = 0xa6;
} else {
r[x+0] = '.';
r[x+1] = '.';
r[x+2] = '.';
}
write_ellipsis(r + x, false);
memcpy(r + x + 3,
s + old_length - (new_length - x - need_space),
new_length - x - need_space + 1);
@ -596,23 +601,56 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
*/
memcpy(e, s, len);
e[len + 0] = 0xe2; /* tri-dot ellipsis: … */
e[len + 1] = 0x80;
e[len + 2] = 0xa6;
write_ellipsis(e + len, true);
memcpy(e + len + 3, j, len2 + 1);
return e;
}
char *ellipsize(const char *s, size_t length, unsigned percent) {
if (length == (size_t) -1)
return strdup(s);
return ellipsize_mem(s, strlen(s), length, percent);
}
char *cellescape(char *buf, size_t len, const char *s) {
/* Escape and ellipsize s into buffer buf of size len. Only non-control ASCII
* characters are copied as they are, everything else is escaped. The result
* is different then if escaping and ellipsization was performed in two
* separate steps, because each sequence is either stored in full or skipped.
*
* This function should be used for logging about strings which expected to
* be plain ASCII in a safe way.
*
* An ellipsis will be used if s is too long. It was always placed at the
* very end.
*/
size_t i;
const char *t = s;
assert(len > 4 + 4 + 1); /* two chars and the terminator */
for (i = 0; i < len - 9; t++) {
if (!*t)
goto done;
i += cescape_char(*t, buf + i);
}
/* We have space for one more char and terminating nul at this point */
if (*t) {
if (*(t+1))
i += write_ellipsis(buf + i, false);
else
i += cescape_char(*t, buf + i);
}
done:
buf[i] = '\0';
return buf;
}
bool nulstr_contains(const char *nulstr, const char *needle) {
const char *i;

View file

@ -157,6 +157,10 @@ bool string_has_cc(const char *p, const char *ok) _pure_;
char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent);
char *ellipsize(const char *s, size_t length, unsigned percent);
char *cellescape(char *buf, size_t len, const char *s);
/* This limit is arbitrary, enough to give some idea what the string contains */
#define CELLESCAPE_DEFAULT_LENGTH 64
bool nulstr_contains(const char *nulstr, const char *needle);

View file

@ -282,8 +282,11 @@ static char *format_timestamp_internal(
return NULL; /* Timestamp is unset */
/* Let's not format times with years > 9999 */
if (t > USEC_TIMESTAMP_FORMATTABLE_MAX)
return NULL;
if (t > USEC_TIMESTAMP_FORMATTABLE_MAX) {
assert(l >= strlen("--- XXXX-XX-XX XX:XX:XX") + 1);
strcpy(buf, "--- XXXX-XX-XX XX:XX:XX");
return buf;
}
sec = (time_t) (t / USEC_PER_SEC); /* Round down */

View file

@ -0,0 +1,75 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "fuzz.h"
#include <sys/mman.h>
#include "sd-journal.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "journal-remote.h"
#include "logs-show.h"
#include "memfd-util.h"
#include "strv.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
_cleanup_fclose_ FILE *dev_null = NULL;
RemoteServer s = {};
char name[] = "/tmp/fuzz-journal-remote.XXXXXX.journal";
void *mem;
int fdin; /* will be closed by journal_remote handler after EOF */
_cleanup_close_ int fdout = -1;
sd_journal *j;
OutputMode mode;
int r;
if (size <= 2)
return 0;
assert_se((fdin = memfd_new_and_map("fuzz-journal-remote", size, &mem)) >= 0);
memcpy(mem, data, size);
assert_se(munmap(mem, size) == 0);
fdout = mkostemps(name, STRLEN(".journal"), O_CLOEXEC);
assert_se(fdout >= 0);
/* In */
assert_se(journal_remote_server_init(&s, name, JOURNAL_WRITE_SPLIT_NONE, false, false) >= 0);
assert_se(journal_remote_add_source(&s, fdin, (char*) "fuzz-data", false) > 0);
while (s.active) {
r = journal_remote_handle_raw_source(NULL, fdin, 0, &s);
assert_se(r >= 0);
}
journal_remote_server_destroy(&s);
assert_se(close(fdin) < 0 && errno == EBADF); /* Check that the fd is closed already */
/* Out */
r = sd_journal_open_files(&j, (const char**) STRV_MAKE(name), 0);
assert_se(r >= 0);
if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0)
assert_se(dev_null = fopen("/dev/null", "we"));
for (mode = 0; mode < _OUTPUT_MODE_MAX; mode++) {
if (!dev_null)
log_info("/* %s */", output_mode_to_string(mode));
r = show_journal(dev_null ?: stdout, j, mode, 0, 0, -1, 0, NULL);
assert_se(r >= 0);
r = sd_journal_seek_head(j);
assert_se(r >= 0);
}
sd_journal_close(j);
unlink(name);
return 0;
}

View file

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 65536

View file

@ -19,4 +19,9 @@ fuzzers += [
[libcore,
libshared],
[libmount]],
[['src/fuzz/fuzz-journal-remote.c'],
[libsystemd_journal_remote,
libshared],
[]],
]

View file

@ -214,7 +214,7 @@ static ssize_t request_reader_entries(
return MHD_CONTENT_READER_END_WITH_ERROR;
}
r = output_journal(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH,
r = show_journal_entry(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH,
NULL, NULL, NULL);
if (r < 0) {
log_error_errno(r, "Failed to serialize item: %m");

File diff suppressed because it is too large Load diff

View file

@ -32,7 +32,6 @@ void source_free(RemoteSource *source) {
* ownership of fd, name, and writer, otherwise does not touch them.
*/
RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) {
RemoteSource *source;
log_debug("Creating source for %sfd:%d (%s)",
@ -75,7 +74,10 @@ int process_source(RemoteSource *source, bool compress, bool seal) {
assert(source->importer.iovw.iovec);
r = writer_write(source->writer, &source->importer.iovw, &source->importer.ts, compress, seal);
if (r < 0)
if (r == -EBADMSG) {
log_error_errno(r, "Entry is invalid, ignoring.");
r = 0;
} else if (r < 0)
log_error_errno(r, "Failed to write entry of %zu bytes: %m",
iovw_size(&source->importer.iovw));
else

View file

@ -92,13 +92,15 @@ int writer_write(Writer *w,
return r;
}
r = journal_file_append_entry(w->journal, ts, iovw->iovec, iovw->count,
r = journal_file_append_entry(w->journal, ts, NULL,
iovw->iovec, iovw->count,
&w->seqnum, NULL, NULL);
if (r >= 0) {
if (w->server)
w->server->event_count += 1;
return 1;
}
return 0;
} else if (r == -EBADMSG)
return r;
log_debug_errno(r, "%s: Write failed, rotating: %m", w->journal->path);
r = do_rotate(&w->journal, compress, seal);
@ -108,12 +110,13 @@ int writer_write(Writer *w,
log_debug("%s: Successfully rotated journal", w->journal->path);
log_debug("Retrying write.");
r = journal_file_append_entry(w->journal, ts, iovw->iovec, iovw->count,
r = journal_file_append_entry(w->journal, ts, NULL,
iovw->iovec, iovw->count,
&w->seqnum, NULL, NULL);
if (r < 0)
return r;
if (w->server)
w->server->event_count += 1;
return 1;
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,8 @@
#include "hashmap.h"
#include "journal-remote-parse.h"
#include "journal-remote-write.h"
#if HAVE_MICROHTTPD
#include "microhttpd-util.h"
typedef struct MHDDaemonWrapper MHDDaemonWrapper;
@ -23,6 +25,7 @@ struct MHDDaemonWrapper {
sd_event_source *io_event;
sd_event_source *timer_event;
};
#endif
struct RemoteServer {
RemoteSource **sources;
@ -36,6 +39,33 @@ struct RemoteServer {
Writer *_single_writer;
uint64_t event_count;
bool check_trust;
#if HAVE_MICROHTTPD
Hashmap *daemons;
#endif
const char *output; /* either the output file or directory */
JournalWriteSplitMode split_mode;
bool compress;
bool seal;
bool check_trust;
};
extern RemoteServer *journal_remote_server_global;
int journal_remote_server_init(
RemoteServer *s,
const char *output,
JournalWriteSplitMode split_mode,
bool compress,
bool seal);
int journal_remote_get_writer(RemoteServer *s, const char *host, Writer **writer);
int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool own_name);
int journal_remote_add_raw_socket(RemoteServer *s, int fd);
int journal_remote_handle_raw_source(
sd_event_source *event,
int fd,
uint32_t revents,
RemoteServer *s);
RemoteServer* journal_remote_server_destroy(RemoteServer *s);

View file

@ -8,12 +8,14 @@
#include <curl/curl.h>
#include <stdbool.h>
#include "sd-daemon.h"
#include "alloc-util.h"
#include "journal-upload.h"
#include "log.h"
#include "string-util.h"
#include "utf8.h"
#include "util.h"
#include "sd-daemon.h"
/**
* Write up to size bytes to buf. Return negative on error, and number of
@ -139,8 +141,12 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
continue;
}
if (!utf8_is_printable_newline(u->field_data,
u->field_length, false)) {
/* We already printed the boot id from the data in
* the header, hence let's suppress it here */
if (memory_startswith(u->field_data, u->field_length, "_BOOT_ID="))
continue;
if (!utf8_is_printable_newline(u->field_data, u->field_length, false)) {
u->entry_state = ENTRY_BINARY_FIELD_START;
continue;
}

View file

@ -5,7 +5,8 @@ import argparse
PARSER = argparse.ArgumentParser()
PARSER.add_argument('n', type=int)
PARSER.add_argument('--dots', action='store_true')
PARSER.add_argument('--data-size', type=int, default=4000)
PARSER.add_argument('-m', '--message-size', type=int, default=200)
PARSER.add_argument('-d', '--data-size', type=int, default=4000)
PARSER.add_argument('--data-type', choices={'random', 'simple'})
OPTIONS = PARSER.parse_args()
@ -42,7 +43,9 @@ bytes = 0
counter = 0
for i in range(OPTIONS.n):
message = repr(src.read(2000))
message = src.read(OPTIONS.message_size)
message = repr(message)[2:-1]
if OPTIONS.data_type == 'random':
data = repr(src.read(OPTIONS.data_size))
else:

View file

@ -8,15 +8,35 @@ systemd_journal_upload_sources = files('''
journal-upload-journal.c
'''.split())
systemd_journal_remote_sources = files('''
libsystemd_journal_remote_sources = files('''
journal-remote-parse.h
journal-remote-parse.c
journal-remote-write.h
journal-remote-write.c
journal-remote.h
journal-remote.c
microhttpd-util.h
microhttpd-util.c
'''.split())
if conf.get('HAVE_MICROHTTPD') == 1
libsystemd_journal_remote_sources += files('''
microhttpd-util.h
microhttpd-util.c
'''.split())
endif
libsystemd_journal_remote = static_library(
'systemd-journal-remote',
libsystemd_journal_remote_sources,
include_directories : includes,
dependencies : [threads,
libmicrohttpd,
libgnutls,
libxz,
liblz4],
install : false)
systemd_journal_remote_sources = files('''
journal-remote-main.c
'''.split())
systemd_journal_gatewayd_sources = files('''

View file

@ -453,7 +453,10 @@ static int journal_file_refresh_header(JournalFile *f) {
assert(f->header);
r = sd_id128_get_machine(&f->header->machine_id);
if (r < 0)
if (IN_SET(r, -ENOENT, -ENOMEDIUM))
/* We don't have a machine-id, let's continue without */
zero(f->header->machine_id);
else if (r < 0)
return r;
r = sd_id128_get_boot(&boot_id);
@ -1798,6 +1801,7 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) {
static int journal_file_append_entry_internal(
JournalFile *f,
const dual_timestamp *ts,
const sd_id128_t *boot_id,
uint64_t xor_hash,
const EntryItem items[], unsigned n_items,
uint64_t *seqnum,
@ -1823,7 +1827,7 @@ static int journal_file_append_entry_internal(
o->entry.realtime = htole64(ts->realtime);
o->entry.monotonic = htole64(ts->monotonic);
o->entry.xor_hash = htole64(xor_hash);
o->entry.boot_id = f->header->boot_id;
o->entry.boot_id = boot_id ? *boot_id : f->header->boot_id;
#if HAVE_GCRYPT
r = journal_file_hmac_put_object(f, OBJECT_ENTRY, o, np);
@ -1944,7 +1948,14 @@ static int entry_item_cmp(const void *_a, const void *_b) {
return 0;
}
int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqnum, Object **ret, uint64_t *offset) {
int journal_file_append_entry(
JournalFile *f,
const dual_timestamp *ts,
const sd_id128_t *boot_id,
const struct iovec iovec[], unsigned n_iovec,
uint64_t *seqnum,
Object **ret, uint64_t *offset) {
unsigned i;
EntryItem *items;
int r;
@ -1955,7 +1966,16 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
assert(f->header);
assert(iovec || n_iovec == 0);
if (!ts) {
if (ts) {
if (!VALID_REALTIME(ts->realtime)) {
log_debug("Invalid realtime timestamp %"PRIu64", refusing entry.", ts->realtime);
return -EBADMSG;
}
if (!VALID_MONOTONIC(ts->monotonic)) {
log_debug("Invalid monotomic timestamp %"PRIu64", refusing entry.", ts->monotonic);
return -EBADMSG;
}
} else {
dual_timestamp_get(&_ts);
ts = &_ts;
}
@ -1986,7 +2006,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
* times for rotating media. */
qsort_safe(items, n_iovec, sizeof(EntryItem), entry_item_cmp);
r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, seqnum, ret, offset);
r = journal_file_append_entry_internal(f, ts, boot_id, xor_hash, items, n_iovec, seqnum, ret, offset);
/* If the memory mapping triggered a SIGBUS then we return an
* IO error and ignore the error code passed down to us, since
@ -3563,12 +3583,13 @@ int journal_file_open_reliably(
deferred_closes, template, ret);
}
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) {
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p) {
uint64_t i, n;
uint64_t q, xor_hash = 0;
int r;
EntryItem *items;
dual_timestamp ts;
const sd_id128_t *boot_id;
assert(from);
assert(to);
@ -3580,6 +3601,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
ts.monotonic = le64toh(o->entry.monotonic);
ts.realtime = le64toh(o->entry.realtime);
boot_id = &o->entry.boot_id;
n = journal_file_entry_n_items(o);
/* alloca() can't take 0, hence let's allocate at least one */
@ -3639,7 +3661,8 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
return r;
}
r = journal_file_append_entry_internal(to, &ts, xor_hash, items, n, seqnum, ret, offset);
r = journal_file_append_entry_internal(to, &ts, boot_id, xor_hash, items, n,
NULL, NULL, NULL);
if (mmap_cache_got_sigbus(to->mmap, to->cache_fd))
return -EIO;

View file

@ -205,7 +205,14 @@ uint64_t journal_file_entry_array_n_items(Object *o) _pure_;
uint64_t journal_file_hash_table_n_items(Object *o) _pure_;
int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset);
int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset);
int journal_file_append_entry(
JournalFile *f,
const dual_timestamp *ts,
const sd_id128_t *boot_id,
const struct iovec iovec[], unsigned n_iovec,
uint64_t *seqno,
Object **ret,
uint64_t *offset);
int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset);
int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset);
@ -229,7 +236,7 @@ int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, uint64_t data_
int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, uint64_t data_offset, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset);
int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p);
void journal_file_dump(JournalFile *f);
void journal_file_print_header(JournalFile *f);

View file

@ -2619,8 +2619,8 @@ int main(int argc, char *argv[]) {
arg_utc * OUTPUT_UTC |
arg_no_hostname * OUTPUT_NO_HOSTNAME;
r = output_journal(stdout, j, arg_output, 0, flags,
arg_output_fields, highlight, &ellipsized);
r = show_journal_entry(stdout, j, arg_output, 0, flags,
arg_output_fields, highlight, &ellipsized);
need_seek = true;
if (r == -EADDRNOTAVAIL)
break;

View file

@ -9,8 +9,21 @@
#include "journald-server.h"
void server_process_native_message(Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len);
void server_process_native_message(
Server *s,
const void *buffer,
size_t buffer_size,
const struct ucred *ucred,
const struct timeval *tv,
const char *label,
size_t label_len);
void server_process_native_file(Server *s, int fd, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len);
void server_process_native_file(
Server *s,
int fd,
const struct ucred *ucred,
const struct timeval *tv,
const char *label,
size_t label_len);
int server_open_native_socket(Server*s);
int server_open_native_socket(Server *s);

View file

@ -692,7 +692,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n
s->last_realtime_clock = ts.realtime;
r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL);
r = journal_file_append_entry(f, &ts, NULL, iovec, n, &s->seqnum, NULL, NULL);
if (r >= 0) {
server_schedule_sync(s, priority);
return;
@ -711,7 +711,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n
return;
log_debug("Retrying write.");
r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL);
r = journal_file_append_entry(f, &ts, NULL, iovec, n, &s->seqnum, NULL, NULL);
if (r < 0)
log_error_errno(r, "Failed to write entry (%zu items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
else
@ -1012,7 +1012,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
goto finish;
}
r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset);
if (r >= 0)
continue;
@ -1031,7 +1031,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
}
log_debug("Retrying write.");
r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset);
if (r < 0) {
log_error_errno(r, "Can't write entry: %m");
goto finish;

View file

@ -44,7 +44,7 @@ int main(int argc, char *argv[]) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
assert_se(r >= 0);
r = journal_file_copy_entry(f, new_journal, o, f->current_offset, NULL, NULL, NULL);
r = journal_file_copy_entry(f, new_journal, o, f->current_offset);
assert_se(r >= 0);
n++;

View file

@ -66,7 +66,7 @@ static void append_number(JournalFile *f, int n, uint64_t *seqnum) {
assert_se(asprintf(&p, "NUMBER=%d", n) >= 0);
iovec[0].iov_base = p;
iovec[0].iov_len = strlen(p);
assert_ret(journal_file_append_entry(f, &ts, iovec, 1, seqnum, NULL, NULL));
assert_ret(journal_file_append_entry(f, &ts, NULL, iovec, 1, seqnum, NULL, NULL));
free(p);
}

View file

@ -109,12 +109,12 @@ int main(int argc, char *argv[]) {
iovec[1].iov_len = strlen(q);
if (i % 10 == 0)
assert_se(journal_file_append_entry(three, &ts, iovec, 2, NULL, NULL, NULL) == 0);
assert_se(journal_file_append_entry(three, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
else {
if (i % 3 == 0)
assert_se(journal_file_append_entry(two, &ts, iovec, 2, NULL, NULL, NULL) == 0);
assert_se(journal_file_append_entry(two, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
assert_se(journal_file_append_entry(one, &ts, iovec, 2, NULL, NULL, NULL) == 0);
assert_se(journal_file_append_entry(one, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
}
free(p);

View file

@ -90,7 +90,7 @@ int main(int argc, char *argv[]) {
iovec.iov_base = (void*) test;
iovec.iov_len = strlen(test);
assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
free(test);
}

View file

@ -23,6 +23,7 @@ static void test_non_empty(void) {
static const char test[] = "TEST1=1", test2[] = "TEST2=2";
Object *o;
uint64_t p;
sd_id128_t fake_boot_id;
char t[] = "/tmp/journal-XXXXXX";
log_set_max_level(LOG_DEBUG);
@ -32,19 +33,20 @@ static void test_non_empty(void) {
assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f) == 0);
dual_timestamp_get(&ts);
assert_se(dual_timestamp_get(&ts));
assert_se(sd_id128_randomize(&fake_boot_id) == 0);
iovec.iov_base = (void*) test;
iovec.iov_len = strlen(test);
assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
iovec.iov_base = (void*) test2;
iovec.iov_len = strlen(test2);
assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
iovec.iov_base = (void*) test;
iovec.iov_len = strlen(test);
assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
assert_se(journal_file_append_entry(f, &ts, &fake_boot_id, &iovec, 1, NULL, NULL, NULL) == 0);
#if HAVE_GCRYPT
journal_file_append_tag(f);
@ -59,6 +61,7 @@ static void test_non_empty(void) {
assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 1);
assert_se(le64toh(o->entry.seqnum) == 3);
assert_se(sd_id128_equal(o->entry.boot_id, fake_boot_id));
assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 0);
@ -177,7 +180,7 @@ static bool check_compressed(uint64_t compress_threshold, uint64_t data_size) {
iovec.iov_base = (void*) data;
iovec.iov_len = data_size;
assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
#if HAVE_GCRYPT
journal_file_append_tag(f);

View file

@ -98,7 +98,7 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
return r;
if (sd_id128_is_null(saved_machine_id))
return -EINVAL;
return -ENOMEDIUM;
}
*ret = saved_machine_id;

View file

@ -474,8 +474,9 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
char since2[FORMAT_TIMESTAMP_MAX];
const char *s1, *s2;
SessionStatusInfo i = {};
int r;
@ -605,8 +606,9 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
char since2[FORMAT_TIMESTAMP_MAX];
const char *s1, *s2;
_cleanup_(user_status_info_clear) UserStatusInfo i = {};
int r;

View file

@ -556,8 +556,9 @@ static void machine_status_info_clear(MachineStatusInfo *info) {
}
static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
char since2[FORMAT_TIMESTAMP_MAX];
const char *s1, *s2;
int ifi = -1;
assert(bus);
@ -902,10 +903,11 @@ typedef struct ImageStatusInfo {
} ImageStatusInfo;
static void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) {
char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char ts_absolute[FORMAT_TIMESTAMP_MAX], *s2;
char bs[FORMAT_BYTES_MAX], *s3;
char bs_exclusive[FORMAT_BYTES_MAX], *s4;
char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX];
char ts_absolute[FORMAT_TIMESTAMP_MAX];
char bs[FORMAT_BYTES_MAX];
char bs_exclusive[FORMAT_BYTES_MAX];
const char *s1, *s2, *s3, *s4;
assert(bus);
assert(i);

View file

@ -697,7 +697,8 @@ int bus_print_property(const char *name, sd_bus_message *m, bool value, bool all
* should it turn out to not be sufficient */
if (endswith(name, "Timestamp") || STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec")) {
char timestamp[FORMAT_TIMESTAMP_MAX], *t;
char timestamp[FORMAT_TIMESTAMP_MAX];
const char *t;
t = format_timestamp(timestamp, sizeof(timestamp), u);
if (t || all)

View file

@ -96,6 +96,7 @@ not_found:
#endif
}
#if HAVE_BLKID
/* Detect RPMB and Boot partitions, which are not listed by blkid.
* See https://github.com/systemd/systemd/issues/5806. */
static bool device_is_mmc_special_partition(struct udev_device *d) {
@ -115,6 +116,7 @@ static bool device_is_block(struct udev_device *d) {
return streq(ss, "block");
}
#endif
int dissect_image(
int fd,

View file

@ -293,19 +293,13 @@ static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, Ou
assert(f);
assert(j);
r = -ENXIO;
if (realtime)
r = safe_atou64(realtime, &x);
if (r < 0)
if (!realtime || r < 0 || !VALID_REALTIME(x))
r = sd_journal_get_realtime_usec(j, &x);
if (r < 0)
return log_error_errno(r, "Failed to get realtime timestamp: %m");
if (x > USEC_TIMESTAMP_FORMATTABLE_MAX) {
log_error("Timestamp cannot be printed");
return -EINVAL;
}
if (IN_SET(mode, OUTPUT_SHORT_FULL, OUTPUT_WITH_UNIT)) {
const char *k;
@ -314,7 +308,7 @@ static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, Ou
else
k = format_timestamp(buf, sizeof(buf), x);
if (!k) {
log_error("Failed to format timestamp.");
log_error("Failed to format timestamp: %"PRIu64, x);
return -EINVAL;
}
@ -422,7 +416,6 @@ static int output_short(
sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
r = parse_fieldv(data, length, fields, ELEMENTSOF(fields));
if (r < 0)
return r;
@ -664,10 +657,8 @@ static int output_export(
JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
const char *c;
/* We already printed the boot id, from the data in
* the header, hence let's suppress it here */
if (length >= 9 &&
startswith(data, "_BOOT_ID="))
/* We already printed the boot id from the data in the header, hence let's suppress it here */
if (memory_startswith(data, length, "_BOOT_ID="))
continue;
c = memchr(data, '=', length);
@ -839,7 +830,7 @@ static int output_json(
if (!eq)
continue;
n = strndup(data, eq - (const char*) data);
n = memdup_suffix0(data, eq - (const char*) data);
if (!n) {
r = log_oom();
goto finish;
@ -862,12 +853,10 @@ static int output_json(
}
}
}
if (r == -EBADMSG) {
log_debug_errno(r, "Skipping message we can't read: %m");
return 0;
}
if (r < 0)
return r;
@ -877,11 +866,13 @@ static int output_json(
SD_JOURNAL_FOREACH_DATA(j, data, length) {
const char *eq;
char *kk, *n;
char *kk;
_cleanup_free_ char *n = NULL;
size_t m;
unsigned u;
/* We already printed the boot id, from the data in the header, hence let's suppress it here */
/* We already printed the boot id from the data in
* the header, hence let's suppress it here */
if (memory_startswith(data, length, "_BOOT_ID="))
continue;
@ -890,33 +881,24 @@ static int output_json(
continue;
m = eq - (const char*) data;
n = strndup(data, m);
n = memdup_suffix0(data, m);
if (!n) {
r = log_oom();
goto finish;
}
if (output_fields && !set_get(output_fields, n)) {
free(n);
if (output_fields && !set_get(output_fields, n))
continue;
}
if (separator) {
if (mode == OUTPUT_JSON_PRETTY)
fputs(",\n\t", f);
else
fputs(", ", f);
}
if (separator)
fputs(mode == OUTPUT_JSON_PRETTY ? ",\n\t" : ", ", f);
u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
if (u == 0) {
if (u == 0)
/* We already printed this, let's jump to the next */
free(n);
separator = false;
continue;
} else if (u == 1) {
else if (u == 1) {
/* Field only appears once, output it directly */
json_escape(f, data, m, flags);
@ -926,12 +908,9 @@ static int output_json(
hashmap_remove(h, n);
free(kk);
free(n);
separator = true;
continue;
} else {
/* Field appears multiple times, output it as array */
json_escape(f, data, m, flags);
@ -958,7 +937,6 @@ static int output_json(
hashmap_remove(h, n);
free(kk);
free(n);
/* Iterate data fields form the beginning */
done = false;
@ -1068,7 +1046,7 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(
[OUTPUT_WITH_UNIT] = output_short,
};
int output_journal(
int show_journal_entry(
FILE *f,
sd_journal *j,
OutputMode mode,
@ -1119,14 +1097,15 @@ static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
return 0;
}
static int show_journal(FILE *f,
sd_journal *j,
OutputMode mode,
unsigned n_columns,
usec_t not_before,
unsigned how_many,
OutputFlags flags,
bool *ellipsized) {
int show_journal(
FILE *f,
sd_journal *j,
OutputMode mode,
unsigned n_columns,
usec_t not_before,
unsigned how_many,
OutputFlags flags,
bool *ellipsized) {
int r;
unsigned line = 0;
@ -1137,14 +1116,18 @@ static int show_journal(FILE *f,
assert(mode >= 0);
assert(mode < _OUTPUT_MODE_MAX);
/* Seek to end */
r = sd_journal_seek_tail(j);
if (r < 0)
return log_error_errno(r, "Failed to seek to tail: %m");
if (how_many == (unsigned) -1)
need_seek = true;
else {
/* Seek to end */
r = sd_journal_seek_tail(j);
if (r < 0)
return log_error_errno(r, "Failed to seek to tail: %m");
r = sd_journal_previous_skip(j, how_many);
if (r < 0)
return log_error_errno(r, "Failed to skip previous: %m");
r = sd_journal_previous_skip(j, how_many);
if (r < 0)
return log_error_errno(r, "Failed to skip previous: %m");
}
for (;;) {
for (;;) {
@ -1178,7 +1161,7 @@ static int show_journal(FILE *f,
line++;
maybe_print_begin_newline(f, &flags);
r = output_journal(f, j, mode, n_columns, flags, NULL, NULL, ellipsized);
r = show_journal_entry(f, j, mode, n_columns, flags, NULL, NULL, ellipsized);
if (r < 0)
return r;
}

View file

@ -19,7 +19,7 @@
#include "time-util.h"
#include "util.h"
int output_journal(
int show_journal_entry(
FILE *f,
sd_journal *j,
OutputMode mode,
@ -28,6 +28,15 @@ int output_journal(
char **output_fields,
size_t highlight[2],
bool *ellipsized);
int show_journal(
FILE *f,
sd_journal *j,
OutputMode mode,
unsigned n_columns,
usec_t not_before,
unsigned how_many,
OutputFlags flags,
bool *ellipsized);
int add_match_this_boot(sd_journal *j, const char *machine);

View file

@ -3948,8 +3948,8 @@ static void print_status_info(
UnitStatusInfo *i,
bool *ellipsized) {
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1, since2[FORMAT_TIMESTAMP_MAX], *s2;
const char *active_on, *active_off, *on, *off, *ss;
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
const char *s1, *s2, *active_on, *active_off, *on, *off, *ss;
_cleanup_free_ char *formatted_path = NULL;
ExecStatusInfo *p;
usec_t timestamp;
@ -4077,7 +4077,7 @@ static void print_status_info(
if (endswith(i->id, ".timer")) {
char tstamp1[FORMAT_TIMESTAMP_RELATIVE_MAX],
tstamp2[FORMAT_TIMESTAMP_MAX];
char *next_rel_time, *next_time;
const char *next_rel_time, *next_time;
dual_timestamp nw, next = {i->next_elapse_real,
i->next_elapse_monotonic};
usec_t next_elapse;
@ -4086,12 +4086,8 @@ static void print_status_info(
dual_timestamp_get(&nw);
next_elapse = calc_next_elapse(&nw, &next);
next_rel_time = format_timestamp_relative(tstamp1,
sizeof(tstamp1),
next_elapse);
next_time = format_timestamp(tstamp2,
sizeof(tstamp2),
next_elapse);
next_rel_time = format_timestamp_relative(tstamp1, sizeof tstamp1, next_elapse);
next_time = format_timestamp(tstamp2, sizeof tstamp2, next_elapse);
if (next_time && next_rel_time)
printf("%s; %s\n", next_time, next_rel_time);

View file

@ -6,6 +6,7 @@
***/
#include "alloc-util.h"
#include "locale-util.h"
#include "macro.h"
#include "string-util.h"
#include "strv.h"
@ -77,6 +78,29 @@ static void test_ascii_strcasecmp_nn(void) {
assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
}
static void test_cellescape(void) {
char buf[40];
assert_se(streq(cellescape(buf, 10, "1"), "1"));
assert_se(streq(cellescape(buf, 10, "12"), "12"));
assert_se(streq(cellescape(buf, 10, "123"), is_locale_utf8() ? "1…" : "1..."));
assert_se(streq(cellescape(buf, 10, "1\011"), "1\\t"));
assert_se(streq(cellescape(buf, 10, "1\020"), "1\\020"));
assert_se(streq(cellescape(buf, 10, "1\020x"), is_locale_utf8() ? "1…" : "1..."));
assert_se(streq(cellescape(buf, 40, "1\020"), "1\\020"));
assert_se(streq(cellescape(buf, 40, "1\020x"), "1\\020x"));
assert_se(streq(cellescape(buf, 40, "\a\b\f\n\r\t\v\\\"'"), "\\a\\b\\f\\n\\r\\t\\v\\\\\\\"\\'"));
assert_se(streq(cellescape(buf, 10, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a..."));
assert_se(streq(cellescape(buf, 11, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a..."));
assert_se(streq(cellescape(buf, 12, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a\\b…" : "\\a\\b..."));
assert_se(streq(cellescape(buf, sizeof buf, "1\020"), "1\\020"));
assert_se(streq(cellescape(buf, sizeof buf, "1\020x"), "1\\020x"));
}
static void test_streq_ptr(void) {
assert_se(streq_ptr(NULL, NULL));
assert_se(!streq_ptr("abc", "cdef"));
@ -422,6 +446,7 @@ int main(int argc, char *argv[]) {
test_string_erase();
test_ascii_strcasecmp_n();
test_ascii_strcasecmp_nn();
test_cellescape();
test_streq_ptr();
test_strstrip();
test_strextend();

View file

@ -120,18 +120,16 @@ static void test_parse_nsec(void) {
}
static void test_format_timespan_one(usec_t x, usec_t accuracy) {
char *r;
char l[FORMAT_TIMESPAN_MAX];
const char *t;
usec_t y;
log_info(USEC_FMT" (at accuracy "USEC_FMT")", x, accuracy);
r = format_timespan(l, sizeof(l), x, accuracy);
assert_se(r);
assert_se(t = format_timespan(l, sizeof l, x, accuracy));
log_info(" = <%s>", t);
log_info(" = <%s>", l);
assert_se(parse_sec(l, &y) >= 0);
assert_se(parse_sec(t, &y) >= 0);
log_info(" = "USEC_FMT, y);
@ -271,13 +269,12 @@ static void test_format_timestamp(void) {
}
}
static void test_format_timestamp_utc_one(usec_t t, const char *result) {
static void test_format_timestamp_utc_one(usec_t val, const char *result) {
char buf[FORMAT_TIMESTAMP_MAX];
const char *t;
assert_se(!format_timestamp_utc(buf, sizeof(buf), t) == !result);
if (result)
assert_se(streq(result, buf));
t = format_timestamp_utc(buf, sizeof(buf), val);
assert_se(streq_ptr(t, result));
}
static void test_format_timestamp_utc(void) {
@ -287,11 +284,12 @@ static void test_format_timestamp_utc(void) {
#if SIZEOF_TIME_T == 8
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Thu 9999-12-30 23:59:59 UTC");
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX");
#elif SIZEOF_TIME_T == 4
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Tue 2038-01-19 03:14:07 UTC");
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX");
#endif
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX+1, NULL);
test_format_timestamp_utc_one(USEC_INFINITY, NULL);
}

1
test/fuzz-corpus/.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
/*/* -whitespace

Binary file not shown.

View file

@ -0,0 +1,180 @@
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12d7;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501873
__MONOTONIC_TIMESTAMP=1753961140951
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=\x1b\r"\x9a\xea]\x90rU\xb0SX5\nY\xebi\xdac\x1f\xde\xb4\xf6\x0e\x8d/!\xd0\x9a\xe8\x8b\xc3#hN\xf4\x9c\x8e\xc5\x92>\xaa\xf8Ih\x13\xd2\xbbOa\xedK\x04\xa449\xf3f\x9e\xfc=\xc9\xc1\x0fe\xb4\xf96\xd5z\xcfQ\xcb\xb1\xb4\xe48\xb3\x9f\x1b
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483516
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000000
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12d8;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501874
__MONOTONIC_TIMESTAMP=1753961140952
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=l\x1a\xf4^\xb1\x14\xfb@\r\xa1\x11\xda0\xe0]3Ms$\x7f06\xde\xd9\x02y\xf9@\n\xe8\x01\x83\xcb\xe0)\xed\x98*>\xa1\xc2Y\xe8IR\x95h\xa1\xbb\x16\xba\xedK\x11\xfcj\x04\xfb\x0b\x9b)p\x10\xecH\x1f\x0b\x89{\xeb'\x0e\x1d\xaa\xcbZ\x86\xe0k1
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483517
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000001
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12d9;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501875
__MONOTONIC_TIMESTAMP=1753961140953
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=MzV_\xbb\xc1\x14f\x84\x15\xf5\xe0\xe6\xd2\x0e6#N\xf1\x1b\xe9Z*\x8f\x8a\x13\xad\xa4%r\x02\xd1\xc4^U\xc0u!\xdfjl\x15\xb6\xcc\x93\x1dRi<\x1a\xa9/\x9c\xcb\xe8\x99\xe3\x1cN\x06\xf0\xb41a\xa7L\x99\xda\x83Q: ]\x1c\xb9Hiz\n\x94
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483518
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000002
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12da;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501876
__MONOTONIC_TIMESTAMP=1753961140954
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=\x8aF\xfcG\xd7\xeeZ\x86\xcb.O\xb1!,2\xbf\x86\\&\x15\xa7\xe6\xe7-\x81\xed\xf8\x7f=\xf7\x90YF\xe1\xe6\x99\x83\x84\r\xe48\x93\xc7\xdd\tJy\x86\\\xb4\xf9\xefT\r\x04\xae\x1d\x99\xfe'\x99m\xc4#\x8d\x89w\xb1\xecC\xaf\xe6\x1b\xfd\xc5\xbc\xfd\xe3w2
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483519
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000003
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12db;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501877
__MONOTONIC_TIMESTAMP=1753961140955
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=`\xc7\r\xb6\xc3NPjc\xa129L\xe1\x17\xa2\x96\xa8w\x0c\x07\x8f\x98\x1eS-N\xb7lt\xc5=\xd1\x93\x10_1\xdc\xa9x\xd1\x8a\n\xb1\x90\xdca\xc4\x94\x98\x92\x00\x90)d{\x96\x9e\xc2A\xbf\x81s\xf82_\xe0;\xc3\x06\x8eO\xe4\x8a5GX\xe1\xff\xea
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483520
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000004
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12dc;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501878
__MONOTONIC_TIMESTAMP=1753961140956
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=\r\t \xdf-\xed\xd5\xde\xa1/\xa5T\x1a\xdd\xf9a\xe2\x8b()\xd5\xf2\x1b\xbcu~\xaa\x97\xc7~\x0e~2\x11\xa0\xb5\xd3\xd7^ \xea\x16\x02{\xd1\xbe\xa02\xad\x00\xba$\xf2\xd5\x7f\x9a\xf0\xf9\xf2\x14\xf0/\xb5\xd3"`\xd8\x8e\xb6w\x1bP\x96\xf1\x0c\xf0#\xd2\x12\x88
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483521
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000005
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12dd;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501879
__MONOTONIC_TIMESTAMP=1753961140957
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=\x1a\x15\xd3\x8d\x98\x83m\xe2\x02\xfa\x81\x98\xef\xa2\x8a\xcc\x10\xc5=q=\xd0\xd7_\x0e\x92D\xb1\xc7 \xaa\xae-\x18\xff\xb0<l5\xf1\x91-\xe8g! \xd8\xac\xadi"\xf8 \xebL\xe6-\xbf=i_@\x9b)B\xac\xa50\xf9\xf1~\xb1c^pTD\x15\xee}
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483522
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000006
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12de;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501880
__MONOTONIC_TIMESTAMP=1753961140958
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=\xe4L \xb4\t\xf3\xfbQ\xb8\x95f{C\x1b\x91\x81\xd2!\xc0f\xa41=\xff\x84W\xf3\x0f=\x9e\x87\xd1\x9f\x86;F\x12\xd6\x1c6B\x07\x08\xdb*\xeem\x9f\xe7\xda\x81n_\x00^\xcf!\x19\x19\xe0\x9cM\x05\xf0\xe9\xe9=\xbc\xba=`inw\xc4Qq\x9cW\xe6
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483523
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000007
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12df;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501881
__MONOTONIC_TIMESTAMP=1753961140959
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=\xda\x80\xe0\xe5@\xa4\x94\xecL\xbd\xe4\xe5\xbd\xc8\xae\x8e\xa9k\xa4\rt\xf2\x17\xe3n!.\xe3\xab*\xe3f{H\x98\x86\xa1=U-\x8cNd+\x90\xbd\x970d\xf7\xee\xd7g\x08c\x12\xf4\x9f3\xd0&\x95\xb0\xac\x1a\xe9k\xda,}\x97`:u\xad\x9e\xfaLj\x11
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483524
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000008
__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12e0;t=4fd05c
__REALTIME_TIMESTAMP=1404101101501882
__MONOTONIC_TIMESTAMP=1753961140960
_BOOT_ID=f446871715504074bf7049ef0718fa93
_TRANSPORT=syslog
PRIORITY=3
SYSLOG_FACILITY=6
SYSLOG_IDENTIFIER=/USR/SBIN/CRON
MESSAGE=\xc0\xb4\xefIe\xc9\xd0\xaf!y\x13\xfdT(k\x9b\xc7\x7fm;\xc2\xbb"\x81\x87\\(-\x9a\x8b\xdd\x17\xf7\x8a\x92\xbd\xdd;\x9f\x99\x87\xf2\xb7\xcf\xf6XtRC\xad\xebT\xa1\xe5\xd9p\xd70\xc1\xb0^\x88g@=\xeb\xd8\xcf\xb7bK"6 \xda\x08\x1bp\xbc\r
_UID=0
_GID=0
_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
_HOSTNAME=hostname
SYSLOG_PID=25721
_PID=25721
_SOURCE_REALTIME_TIMESTAMP=1404101101483525
DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000009