You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
4.4 KiB
124 lines
4.4 KiB
From beef22775206d99b06c95c9a015e1b17bf3e767f Mon Sep 17 00:00:00 2001 |
|
From: Jan Synacek <jsynacek@redhat.com> |
|
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_;
|
|
|