Hi here
I'm come again : )

Fragmented arg will do fetch at every encode time, each fetch may get
different result if SMP_F_MAY_CHANGE, for example the fetch <res.payload>,
but the length already encoded in first fragment of the frame, that will
cause SPOA decode failed and waste resources.

Best regards
From 342258c94fbe8ed146e8490fb80a2a7c40cb9075 Mon Sep 17 00:00:00 2001
From: Kevin Zhu <[email protected]>
Date: Fri, 26 Apr 2019 14:00:01 +0800
Subject: [PATCH] BUG/MEDIUM: spoe: arg len encoded in previous frag frame but
 len changed

Fragmented arg will do fetch at every encode time, each fetch may get
different result if SMP_F_MAY_CHANGE, for example res.payload, but
the length already encoded in first fragment of the frame, that will
cause SPOA decode failed and waste resources.
---
 include/proto/spoe.h | 7 ++++---
 include/types/spoe.h | 1 +
 src/flt_spoe.c       | 3 ++-
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/include/proto/spoe.h b/include/proto/spoe.h
index e5b3b4b..86328ad 100644
--- a/include/proto/spoe.h
+++ b/include/proto/spoe.h
@@ -121,7 +121,7 @@ spoe_decode_buffer(char **buf, char *end, char **str, uint64_t *len)
  * many bytes has been encoded. If <*off> is zero at the end, it means that all
  * data has been encoded. */
 static inline int
-spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end)
+spoe_encode_data(unsigned int *len, struct sample *smp, unsigned int *off, char **buf, char *end)
 {
 	char *p = *buf;
 	int   ret;
@@ -185,15 +185,16 @@ spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end)
 							      end);
 				if (ret == -1)
 					return -1;
+				*len = chk->data;
 			}
 			else {
 				/* The sample has been fragmented, encode remaining data */
-				ret = MIN(chk->data - *off, end - p);
+				ret = MIN(*len - *off, end - p);
 				memcpy(p, chk->area + *off, ret);
 				p += ret;
 			}
 			/* Now update <*off> */
-			if (ret + *off != chk->data)
+			if (ret + *off != *len)
 				*off += ret;
 			else
 				*off = 0;
diff --git a/include/types/spoe.h b/include/types/spoe.h
index a744cd7..0ab5d5a 100644
--- a/include/types/spoe.h
+++ b/include/types/spoe.h
@@ -323,6 +323,7 @@ struct spoe_context {
 		struct spoe_message *curmsg;      /* SPOE message from which to resume encoding */
 		struct spoe_arg     *curarg;      /* SPOE arg in <curmsg> from which to resume encoding */
 		unsigned int         curoff;      /* offset in <curarg> from which to resume encoding */
+		unsigned int         len;         /* length of <curarg> need to be encode, for SMP_F_MAY_CHANGE data */
 		unsigned int         flags;       /* SPOE_FRM_FL_* */
 	} frag_ctx; /* Info about fragmented frames, valid on if SPOE_CTX_FL_FRAGMENTED is set */
 
diff --git a/src/flt_spoe.c b/src/flt_spoe.c
index 63d40a6..b1a8788 100644
--- a/src/flt_spoe.c
+++ b/src/flt_spoe.c
@@ -2182,6 +2182,7 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx,
 	list_for_each_entry(arg, &msg->args, list) {
 		ctx->frag_ctx.curarg = arg;
 		ctx->frag_ctx.curoff = UINT_MAX;
+		ctx->frag_ctx.curlen = 0;
 
 	  encode_argument:
 		if (ctx->frag_ctx.curoff != UINT_MAX)
@@ -2196,7 +2197,7 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx,
 
 		/* Fetch the argument value */
 		smp = sample_process(s->be, s->sess, s, dir|SMP_OPT_FINAL, arg->expr, NULL);
-		ret = spoe_encode_data(smp, &ctx->frag_ctx.curoff, buf, end);
+		ret = spoe_encode_data(&ctx->frag_ctx.len, smp, &ctx->frag_ctx.curoff, buf, end);
 		if (ret == -1 || ctx->frag_ctx.curoff)
 			goto too_big;
 	}
-- 
2.7.4

Reply via email to