BUG/MINOR: log: improper behavior when escaping log data

Patrick Hemmer reported an improper log behavior when using
log-format to escape log data (+E option):
Some bytes were truncated from the output:

- escape_string() function now takes an extra parameter that
  allow the caller to specify input string stop pointer in
  case the input string is not guaranteed to be zero-terminated.
- Minors checks were added into lf_text_len() to make sure dst
  string will not overflow.
- lf_text_len() now makes proper use of escape_string() function.

This should be backported as far as 1.8.

(cherry picked from commit c5bff8e550cf49b0cb3a7abb998b2c915323eca9)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 9779c1b5d758310640018cee20b52ccd1cbd0d19)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit dd1d6fcd153e725b7067f5744b18140242bbd1a1)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/log.c b/src/log.c
index c431937..67283f4 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1381,17 +1381,21 @@
 	}
 
 	if (src && len) {
-		if (++len > size)
-			len = size;
+		/* escape_string and strlcpy2 will both try to add terminating NULL-byte
+		 * to dst, so we need to make sure that extra byte will fit into dst
+		 * before calling them
+		 */
 		if (node->options & LOG_OPT_ESC) {
 			char *ret;
 
-			ret = escape_string(dst, dst + len, '\\', rfc5424_escape_map, src);
+			ret = escape_string(dst, (dst + size - 1), '\\', rfc5424_escape_map, src, src + len);
 			if (ret == NULL || *ret != '\0')
 				return NULL;
 			len = ret - dst;
 		}
 		else {
+			if (++len > size)
+				len = size;
 			len = strlcpy2(dst, src, len);
 		}
 
@@ -1402,6 +1406,7 @@
 		if (size < 2)
 			return NULL;
 		*(dst++) = '-';
+		size -= 1;
 	}
 
 	if (node->options & LOG_OPT_QUOTE) {
diff --git a/src/tools.c b/src/tools.c
index da0c8d7..746e0d0 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1935,7 +1935,8 @@
 
 /*
  * Tries to prefix characters tagged in the <map> with the <escape>
- * character. The input <string> must be zero-terminated. The result will
+ * character. The input <string> is processed until string_stop
+ * is reached or NULL-byte is encountered. The result will
  * be stored between <start> (included) and <stop> (excluded). This
  * function will always try to terminate the resulting string with a '\0'
  * before <stop>, and will return its position if the conversion
@@ -1943,11 +1944,11 @@
  */
 char *escape_string(char *start, char *stop,
 		    const char escape, const long *map,
-		    const char *string)
+		    const char *string, const char *string_stop)
 {
 	if (start < stop) {
 		stop--; /* reserve one byte for the final '\0' */
-		while (start < stop && *string != '\0') {
+		while (start < stop && string < string_stop && *string != '\0') {
 			if (!ha_bit_test((unsigned char)(*string), map))
 				*start++ = *string;
 			else {