core: rework serialization

Let's be more careful with what we serialize: let's ensure we never
serialize strings that are longer than LONG_LINE_MAX, so that we know we
can read them back with read_line(…, LONG_LINE_MAX, …) safely.

In order to implement this all serialization functions are move to
serialize.[ch], and internally will do line size checks. We'd rather
skip a serialization line (with a loud warning) than write an overly
long line out. Of course, this is just a second level protection, after
all the data we serialize shouldn't be this long in the first place.

While we are at it also clean up logging: while serializing make sure to
always log about errors immediately. Also, (void)ify all calls we don't
expect errors in (or catch errors as part of the general
fflush_and_check() at the end.
This commit is contained in:
Lennart Poettering
2018-10-26 10:52:41 +02:00
parent cdd620e346
commit d68c645bd3
31 changed files with 519 additions and 462 deletions
+1 -58
View File
@@ -24,6 +24,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "serialize.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
@@ -530,64 +531,6 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
return buf;
}
void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
assert(f);
assert(name);
assert(t);
if (!dual_timestamp_is_set(t))
return;
fprintf(f, "%s="USEC_FMT" "USEC_FMT"\n",
name,
t->realtime,
t->monotonic);
}
int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
uint64_t a, b;
int r, pos;
assert(value);
assert(t);
pos = strspn(value, WHITESPACE);
if (value[pos] == '-')
return -EINVAL;
pos += strspn(value + pos, DIGITS);
pos += strspn(value + pos, WHITESPACE);
if (value[pos] == '-')
return -EINVAL;
r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
if (r != 2) {
log_debug("Failed to parse dual timestamp value \"%s\".", value);
return -EINVAL;
}
if (value[pos] != '\0')
/* trailing garbage */
return -EINVAL;
t->realtime = a;
t->monotonic = b;
return 0;
}
int timestamp_deserialize(const char *value, usec_t *timestamp) {
int r;
assert(value);
r = safe_atou64(value, timestamp);
if (r < 0)
return log_debug_errno(r, "Failed to parse timestamp value \"%s\": %m", value);
return r;
}
static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
static const struct {
const char *name;