Package: haproxy / 1.5.8-3+deb8u2

from-upstream/0006-BUG-MEDIUM-pattern-don-t-load-more-than-once-a-patte.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
From a0e753b688853c7ac751bcb183978eba063e68f1 Mon Sep 17 00:00:00 2001
From: Thierry FOURNIER <tfournier@exceliance.fr>
Date: Mon, 24 Nov 2014 11:14:42 +0100
Subject: [PATCH 6/9] BUG/MEDIUM: pattern: don't load more than once a pattern
 list.

A memory optimization can use the same pattern expression for many
equal pattern list (same parse method, index method and index_smp
method).

The pattern expression is returned by "pattern_new_expr", but this
function dont indicate if the returned pattern is already in use.

So, the caller function reload the list of patterns in addition with
the existing patterns. This behavior is not a problem with tree indexed
pattern, but it grows the lists indexed patterns.

This fix add a "reuse" flag in return of the function "pattern_new_expr".
If the flag is set, I suppose that the patterns are already loaded.

This fix must be backported into 1.5.
(cherry picked from commit 315ec4217f912f6cc8fcf98624d852f9cd8399f9)
---
 include/proto/pattern.h |  3 ++-
 src/acl.c               |  2 +-
 src/pattern.c           | 22 ++++++++++++++++++++--
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/include/proto/pattern.h b/include/proto/pattern.h
index 4a969ac199e4..7855474e5b44 100644
--- a/include/proto/pattern.h
+++ b/include/proto/pattern.h
@@ -206,7 +206,8 @@ int pattern_read_from_file(struct pattern_head *head, unsigned int refflags, con
  */
 void pattern_init_expr(struct pattern_expr *expr);
 struct pattern_expr *pattern_lookup_expr(struct pattern_head *head, struct pat_ref *ref);
-struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref *ref, char **err);
+struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref *ref,
+                                      char **err, int *reuse);
 struct sample_storage **pattern_find_smp(struct pattern_expr *expr, struct pat_ref_elt *elt);
 int pattern_delete(struct pattern_expr *expr, struct pat_ref_elt *ref);
 
diff --git a/src/acl.c b/src/acl.c
index 8f3fd9eaa746..d8b3000c0c36 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -532,7 +532,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
 	}
 
 	/* Create new pattern expression associated to this reference. */
-	pattern_expr = pattern_new_expr(&expr->pat, ref, err);
+	pattern_expr = pattern_new_expr(&expr->pat, ref, err, NULL);
 	if (!pattern_expr)
 		goto out_free_expr;
 
diff --git a/src/pattern.c b/src/pattern.c
index c63365d74bf7..20547f9607be 100644
--- a/src/pattern.c
+++ b/src/pattern.c
@@ -1855,12 +1855,19 @@ struct pattern_expr *pattern_lookup_expr(struct pattern_head *head, struct pat_r
  * <ref> can be NULL. If an error is occured, the function returns NULL and
  * <err> is filled. Otherwise, the function returns new pattern_expr linked
  * with <head> and <ref>.
+ *
+ * The returned value can be a alredy filled pattern list, in this case the
+ * flag <reuse> is set.
  */
-struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref *ref, char **err)
+struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref *ref,
+                                      char **err, int *reuse)
 {
 	struct pattern_expr *expr;
 	struct pattern_expr_list *list;
 
+	if (reuse)
+		*reuse = 0;
+
 	/* Memory and initialization of the chain element. */
 	list = malloc(sizeof(*list));
 	if (!list) {
@@ -1915,6 +1922,8 @@ struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref
 		 * with ref and we must not free it.
 		 */
 		list->do_free = 0;
+		if (reuse)
+			*reuse = 1;
 	}
 
 	/* The new list element reference the pattern_expr. */
@@ -2087,6 +2096,7 @@ int pattern_read_from_file(struct pattern_head *head, unsigned int refflags,
 	struct pat_ref *ref;
 	struct pattern_expr *expr;
 	struct pat_ref_elt *elt;
+	int reuse;
 
 	/* Lookup for the existing reference. */
 	ref = pat_ref_lookup(filename);
@@ -2161,12 +2171,20 @@ int pattern_read_from_file(struct pattern_head *head, unsigned int refflags,
 	 */
 	expr = pattern_lookup_expr(head, ref);
 	if (!expr || (expr->mflags != patflags)) {
-		expr = pattern_new_expr(head, ref, err);
+		expr = pattern_new_expr(head, ref, err, &reuse);
 		if (!expr)
 			return 0;
 		expr->mflags = patflags;
 	}
 
+	/* The returned expression may be not empty, because the function
+	 * "pattern_new_expr" lookup for similar pattern list and can
+	 * reuse a already filled pattern list. In this case, we can not
+	 * reload the patterns.
+	 */
+	if (reuse)
+		return 1;
+
 	/* Load reference content in the pattern expression. */
 	list_for_each_entry(elt, &ref->head, list) {
 		if (!pat_ref_push(elt, expr, patflags, err)) {
-- 
2.1.3