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

