From beef22775206d99b06c95c9a015e1b17bf3e767f Mon Sep 17 00:00:00 2001 From: Jan Synacek Date: Thu, 23 Nov 2017 10:13:52 +0100 Subject: [PATCH] conf-parse: remove 4K line length limit Let's use read_line() to solve our long line limitation. Fixes #3302. (cherry picked from commit e6dde451a51dc5aaa7f4d98d39b8fe735f73d2af) Resolves: #1503106 --- src/shared/conf-parser.c | 50 +++++++++++++++++++++++++++++----------- src/shared/utf8.h | 1 + 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 0b1af6c57..73e4d49ea 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -28,6 +28,8 @@ #include "conf-parser.h" #include "conf-files.h" +#include "def.h" +#include "fileio.h" #include "util.h" #include "macro.h" #include "strv.h" @@ -339,7 +341,7 @@ int config_parse(const char *unit, _cleanup_free_ char *section = NULL, *continuation = NULL; _cleanup_fclose_ FILE *ours = NULL; unsigned line = 0, section_line = 0; - bool section_ignored = false; + bool section_ignored = false, allow_bom = true; int r; assert(filename); @@ -359,21 +361,45 @@ int config_parse(const char *unit, fd_warn_permissions(filename, fileno(f)); - while (!feof(f)) { - char l[LINE_MAX], *p, *c = NULL, *e; + for (;;) { + _cleanup_free_ char *buf = NULL; + char *l, *p, *c = NULL, *e; bool escaped = false; - if (!fgets(l, sizeof(l), f)) { - if (feof(f)) - break; + r = read_line(f, LONG_LINE_MAX, &buf); + if (r == 0) + break; + if (r == -ENOBUFS) { + if (warn) + log_error_errno(r, "%s:%u: Line too long", filename, line); - log_error_errno(errno, "Failed to read configuration file '%s': %m", filename); - return -errno; + return r; + } + if (r < 0) { + if (warn) + log_error_errno(r, "%s:%u: Error while reading configuration file: %m", filename, line); + + return r; } - truncate_nl(l); + l = buf; + if (allow_bom) { + char *q; + + q = startswith(buf, UTF8_BYTE_ORDER_MARK); + if (q) { + l = q; + allow_bom = false; + } + } if (continuation) { + if (strlen(continuation) + strlen(l) > LONG_LINE_MAX) { + if (warn) + log_error("%s:%u: Continuation line too long", filename, line); + return -ENOBUFS; + } + c = strappend(continuation, l); if (!c) { if (warn) @@ -381,8 +407,7 @@ int config_parse(const char *unit, return -ENOMEM; } - free(continuation); - continuation = NULL; + continuation = mfree(continuation); p = c; } else p = l; @@ -428,8 +453,7 @@ int config_parse(const char *unit, if (r < 0) { if (warn) - log_warning_errno(r, "Failed to parse file '%s': %m", - filename); + log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line); return r; } } diff --git a/src/shared/utf8.h b/src/shared/utf8.h index 77f663438..d31737061 100644 --- a/src/shared/utf8.h +++ b/src/shared/utf8.h @@ -26,6 +26,7 @@ #include "macro.h" #define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd" +#define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf" const char *utf8_is_valid(const char *s) _pure_; char *ascii_is_valid(const char *s) _pure_;