[PATCH] Handle long lines properly

From: <ole#ans.pl>
Date: Thu, 01 Nov 2007 00:41:53 +0100


From 9260147f45cb95827045ef83039078b147682322 Mon Sep 17 00:00:00 2001 From: Krzysztof Piotr Oledzki <ole#ans.pl> Date: Thu, 1 Nov 2007 00:33:12 +0100
Subject: [MEDIUM] Handle long lines properly

Currently, there is a hidden line length limit in the haproxy, set to 256-1 chars. With large acls (for example many hdr(host) matches) it may be not enough and which is even worse, error message may be totally confusing as everything above this limit is treated as a next line:

echo -ne "frontend aqq 1.2.3.4:80\nmode http\nacl e hdr(host) -i X X X X X X X www.xx.example.com stats\n"|  sed s/X/www.some-host-name.example.com/g > ha.cfg && haproxy -c -f ./ha.cfg

[WARNING] 300/163906 (11342) : parsing [./ha.cfg:4] : 'stats' ignored because frontend 'aqq' has no backend capability.

Recently I hit simmilar problem and it took me a while to find why requests for "stats" are not handled properly.

This patch:

With this patch, when LINESIZE is defined to 256, above example produces: [ALERT] 300/164724 (27364) : parsing [/tmp/ha.cfg:3]: line too long, limit: 255. [ALERT] 300/164724 (27364) : Error reading configuration file : /tmp/ha.cfg

---
 include/common/defaults.h |    7 ++++++-
 src/cfgparse.c            |   24 +++++++++++++++++-------
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/include/common/defaults.h b/include/common/defaults.h
index 5b18767..1a69f40 100644
--- a/include/common/defaults.h
+++ b/include/common/defaults.h
@@ -43,8 +43,13 @@
 #define REQURI_LEN      1024
 #define CAPTURE_LEN     64
 
+// maximum line size when parsing config
+#ifndef LINESIZE
+#define LINESIZE	2048
+#endif
+
 // max # args on a configuration line
-#define MAX_LINE_ARGS   40
+#define MAX_LINE_ARGS   64
 
 // max # of added headers per request
 #define MAX_NEWHDR      10
diff --git a/src/cfgparse.c b/src/cfgparse.c
index d722b0b..c0641a2 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -2298,13 +2298,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
  */
 int readcfgfile(const char *file)
 {
-	char thisline[256];
-	char *line;
+	char thisline[LINESIZE];
 	FILE *f;
 	int linenum = 0;
-	char *end;
-	char *args[MAX_LINE_ARGS + 1];
-	int arg;
 	int cfgerr = 0;
 	int confsect = CFG_NONE;
 
@@ -2316,11 +2312,25 @@ int readcfgfile(const char *file)
 
 	init_default_instance();
 
-	while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
+	while (fgets(thisline, sizeof(thisline), f) != NULL) {
+		int arg;
+		char *end;
+		char *args[MAX_LINE_ARGS + 1];
+		char *line = thisline;
+
 		linenum++;
 
 		end = line + strlen(line);
 
+		if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
+			/* Check if we reached the limit and the last char is not \n.
+			 * Watch out for the last line without the terminating '\n'!
+			 */
+			Alert("parsing [%s:%d]: line too long, limit: %d.\n",
+				file, linenum, sizeof(thisline)-1);
+			return -1;
+		}
+
 		/* skip leading spaces */
 		while (isspace((unsigned char)*line))
 			line++;
@@ -2378,7 +2388,7 @@ int readcfgfile(const char *file)
 			}
 			else if (isspace((unsigned char)*line)) {
 				/* a non-escaped space is an argument separator */
-				*line++ = 0;
+				*line++ = '\0';
 				while (isspace((unsigned char)*line))
 					line++;
 				args[++arg] = line;
-- 
1.5.3.4
Received on 2007/11/01 00:41

This archive was generated by hypermail 2.2.0 : 2007/11/04 19:21 CET