gplv2/haproxy/haproxy/haproxy-env-var.patch

246 lines
11 KiB
Diff

Index: haproxy-1.5.11/src/cfgparse.c
===================================================================
--- haproxy-1.5.11.orig/src/cfgparse.c
+++ haproxy-1.5.11/src/cfgparse.c
@@ -5789,12 +5789,19 @@ out:
*/
int readcfgfile(const char *file)
{
- char thisline[LINESIZE];
+ char *thisline;
+ int linesize = LINESIZE;
FILE *f;
int linenum = 0;
int err_code = 0;
struct cfg_section *cs = NULL;
struct cfg_section *ics;
+ int readbytes = 0;
+
+ if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
+ Alert("parsing [%s] : out of memory.\n", file);
+ return -1;
+ }
/* Register internal sections */
if (!cfg_register_section("listen", cfg_parse_listen) ||
@@ -5810,11 +5817,14 @@ int readcfgfile(const char *file)
if ((f=fopen(file,"r")) == NULL)
return -1;
- while (fgets(thisline, sizeof(thisline), f) != NULL) {
+next_line:
+ while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
int arg, kwm = KWM_STD;
char *end;
char *args[MAX_LINE_ARGS + 1];
char *line = thisline;
+ int dquote = 0; /* double quote */
+ int squote = 0; /* simple quote */
linenum++;
@@ -5824,11 +5834,25 @@ int readcfgfile(const char *file)
/* 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, (int)sizeof(thisline)-1);
- err_code |= ERR_ALERT | ERR_FATAL;
+ char *newline;
+ int newlinesize = linesize * 2;
+
+ newline = realloc(thisline, sizeof(*thisline) * newlinesize);
+ if (newline == NULL) {
+ Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
+ file, linenum);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ continue;
+ }
+
+ readbytes = linesize - 1;
+ linesize = newlinesize;
+ thisline = newline;
+ continue;
}
+ readbytes = 0;
+
/* skip leading spaces */
while (isspace((unsigned char)*line))
line++;
@@ -5837,10 +5861,26 @@ int readcfgfile(const char *file)
args[arg] = line;
while (*line && arg < MAX_LINE_ARGS) {
- /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
- * C equivalent value. Other combinations left unchanged (eg: \1).
- */
- if (*line == '\\') {
+ if (*line == '"' && !squote) { /* double quote outside single quotes */
+ if (dquote)
+ dquote = 0;
+ else
+ dquote = 1;
+ memmove(line, line + 1, end - line);
+ end--;
+ }
+ else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
+ if (squote)
+ squote = 0;
+ else
+ squote = 1;
+ memmove(line, line + 1, end - line);
+ end--;
+ }
+ else if (*line == '\\' && !squote) {
+ /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
+ * C equivalent value. Other combinations left unchanged (eg: \1).
+ */
int skip = 0;
if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
*line = line[1];
@@ -5872,6 +5912,15 @@ int readcfgfile(const char *file)
Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
}
+ } else if (line[1] == '"') {
+ *line = '"';
+ skip = 1;
+ } else if (line[1] == '\'') {
+ *line = '\'';
+ skip = 1;
+ } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
+ *line = '$';
+ skip = 1;
}
if (skip) {
memmove(line + 1, line + 1 + skip, end - (line + skip));
@@ -5879,23 +5928,117 @@ int readcfgfile(const char *file)
}
line++;
}
- else if (*line == '#' || *line == '\n' || *line == '\r') {
+ else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
/* end of string, end of loop */
*line = 0;
break;
}
- else if (isspace((unsigned char)*line)) {
+ else if (!squote && !dquote && isspace((unsigned char)*line)) {
/* a non-escaped space is an argument separator */
*line++ = '\0';
while (isspace((unsigned char)*line))
line++;
args[++arg] = line;
}
+ else if (dquote && *line == '$') {
+ /* environment variables are evaluated inside double quotes */
+ char *var_beg;
+ char *var_end;
+ char save_char;
+ char *value;
+ int val_len;
+ int newlinesize;
+ int braces = 0;
+
+ var_beg = line + 1;
+ var_end = var_beg;
+
+ if (*var_beg == '{') {
+ var_beg++;
+ var_end++;
+ braces = 1;
+ }
+
+ if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
+ Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto next_line; /* skip current line */
+ }
+
+ while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
+ var_end++;
+
+ save_char = *var_end;
+ *var_end = '\0';
+ value = getenv(var_beg);
+ *var_end = save_char;
+ val_len = value ? strlen(value) : 0;
+
+ if (braces) {
+ if (*var_end == '}') {
+ var_end++;
+ braces = 0;
+ } else {
+ Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto next_line; /* skip current line */
+ }
+ }
+
+ newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
+
+ /* if not enough space in thisline */
+ if (newlinesize > linesize) {
+ char *newline;
+
+ newline = realloc(thisline, newlinesize * sizeof(*thisline));
+ if (newline == NULL) {
+ Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto next_line; /* slip current line */
+ }
+ /* recompute pointers if realloc returns a new pointer */
+ if (newline != thisline) {
+ int i;
+ int diff;
+
+ for (i = 0; i <= arg; i++) {
+ diff = args[i] - thisline;
+ args[i] = newline + diff;
+ }
+
+ diff = var_end - thisline;
+ var_end = newline + diff;
+ diff = end - thisline;
+ end = newline + diff;
+ diff = line - thisline;
+ line = newline + diff;
+ thisline = newline;
+ }
+ linesize = newlinesize;
+ }
+
+ /* insert value inside the line */
+ memmove(line + val_len, var_end, end - var_end + 1);
+ memcpy(line, value, val_len);
+ end += val_len - (var_end - line);
+ line += val_len;
+ }
else {
line++;
}
}
+ if (dquote) {
+ Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+
+ if (squote) {
+ Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+
/* empty line */
if (!**args)
continue;
@@ -5966,6 +6109,7 @@ int readcfgfile(const char *file)
break;
}
cursection = NULL;
+ free(thisline);
fclose(f);
return err_code;
}