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