summaryrefslogtreecommitdiffstats
path: root/src/shared/serialize.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-09-11 12:21:14 +0200
committerLuca Boccassi <luca.boccassi@gmail.com>2023-09-11 21:40:35 +0200
commitf96a32c7f06995bd17daa311f491682f524e48a6 (patch)
tree9bbc25793f0581c491cfbe792ae62f4d5fa4695b /src/shared/serialize.c
parentlogind: add PrepareForShutdownWithMetadata signal (diff)
downloadsystemd-f96a32c7f06995bd17daa311f491682f524e48a6.tar.xz
systemd-f96a32c7f06995bd17daa311f491682f524e48a6.zip
serialize: don#t allocate 1M on the stack just like that
Prompted by: https://github.com/systemd/systemd/pull/27890#issuecomment-1712841117
Diffstat (limited to '')
-rw-r--r--src/shared/serialize.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/src/shared/serialize.c b/src/shared/serialize.c
index 669071dbd8..b750bae576 100644
--- a/src/shared/serialize.c
+++ b/src/shared/serialize.c
@@ -24,10 +24,8 @@ int serialize_item(FILE *f, const char *key, const char *value) {
/* Make sure that anything we serialize we can also read back again with read_line() with a maximum line size
* of LONG_LINE_MAX. This is a safety net only. All code calling us should filter this out earlier anyway. */
- if (strlen(key) + 1 + strlen(value) + 1 > LONG_LINE_MAX) {
- log_warning("Attempted to serialize overly long item '%s', refusing.", key);
- return -EINVAL;
- }
+ if (strlen(key) + 1 + strlen(value) + 1 > LONG_LINE_MAX)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Attempted to serialize overly long item '%s', refusing.", key);
fputs(key, f);
fputc('=', f);
@@ -54,7 +52,10 @@ int serialize_item_escaped(FILE *f, const char *key, const char *value) {
}
int serialize_item_format(FILE *f, const char *key, const char *format, ...) {
- char buf[LONG_LINE_MAX];
+ _cleanup_free_ char *allocated = NULL;
+ char buf[256]; /* Something resonably short that fits nicely on any stack (i.e. is considerably less
+ * than LONG_LINE_MAX (1MiB!) */
+ const char *b;
va_list ap;
int k;
@@ -62,18 +63,35 @@ int serialize_item_format(FILE *f, const char *key, const char *format, ...) {
assert(key);
assert(format);
+ /* First, let's try to format this into a stack buffer */
va_start(ap, format);
k = vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
- if (k < 0 || (size_t) k >= sizeof(buf) || strlen(key) + 1 + k + 1 > LONG_LINE_MAX) {
- log_warning("Attempted to serialize overly long item '%s', refusing.", key);
- return -EINVAL;
+ if (k < 0)
+ return log_warning_errno(errno, "Failed to serialize item '%s', ignoring: %m", key);
+ if (strlen(key) + 1 + k + 1 > LONG_LINE_MAX) /* See above */
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Attempted to serialize overly long item '%s', refusing.", key);
+
+ if ((size_t) k < sizeof(buf))
+ b = buf; /* Yay, it fit! */
+ else {
+ /* So the string didn't fit in the short buffer above, but was not above our total limit,
+ * hence let's format it via dynamic memory */
+
+ va_start(ap, format);
+ k = vasprintf(&allocated, format, ap);
+ va_end(ap);
+
+ if (k < 0)
+ return log_warning_errno(errno, "Failed to serialize item '%s', ignoring: %m", key);
+
+ b = allocated;
}
fputs(key, f);
fputc('=', f);
- fputs(buf, f);
+ fputs(b, f);
fputc('\n', f);
return 1;