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. This patch must be backported to 1.9 and 1.8.
This commit is contained in:
parent
1907ccc2f7
commit
f7f54280c8
|
@ -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
|
* many bytes has been encoded. If <*off> is zero at the end, it means that all
|
||||||
* data has been encoded. */
|
* data has been encoded. */
|
||||||
static inline int
|
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;
|
char *p = *buf;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -185,15 +185,16 @@ spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end)
|
||||||
end);
|
end);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
*len = chk->data;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* The sample has been fragmented, encode remaining data */
|
/* 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);
|
memcpy(p, chk->area + *off, ret);
|
||||||
p += ret;
|
p += ret;
|
||||||
}
|
}
|
||||||
/* Now update <*off> */
|
/* Now update <*off> */
|
||||||
if (ret + *off != chk->data)
|
if (ret + *off != *len)
|
||||||
*off += ret;
|
*off += ret;
|
||||||
else
|
else
|
||||||
*off = 0;
|
*off = 0;
|
||||||
|
|
|
@ -323,6 +323,7 @@ struct spoe_context {
|
||||||
struct spoe_message *curmsg; /* SPOE message from which to resume encoding */
|
struct spoe_message *curmsg; /* SPOE message from which to resume encoding */
|
||||||
struct spoe_arg *curarg; /* SPOE arg in <curmsg> 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 curoff; /* offset in <curarg> from which to resume encoding */
|
||||||
|
unsigned int curlen; /* length of <curarg> need to be encode, for SMP_F_MAY_CHANGE data */
|
||||||
unsigned int flags; /* SPOE_FRM_FL_* */
|
unsigned int flags; /* SPOE_FRM_FL_* */
|
||||||
} frag_ctx; /* Info about fragmented frames, valid on if SPOE_CTX_FL_FRAGMENTED is set */
|
} frag_ctx; /* Info about fragmented frames, valid on if SPOE_CTX_FL_FRAGMENTED is set */
|
||||||
|
|
||||||
|
|
|
@ -2182,6 +2182,7 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx,
|
||||||
list_for_each_entry(arg, &msg->args, list) {
|
list_for_each_entry(arg, &msg->args, list) {
|
||||||
ctx->frag_ctx.curarg = arg;
|
ctx->frag_ctx.curarg = arg;
|
||||||
ctx->frag_ctx.curoff = UINT_MAX;
|
ctx->frag_ctx.curoff = UINT_MAX;
|
||||||
|
ctx->frag_ctx.curlen = 0;
|
||||||
|
|
||||||
encode_argument:
|
encode_argument:
|
||||||
if (ctx->frag_ctx.curoff != UINT_MAX)
|
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 */
|
/* Fetch the argument value */
|
||||||
smp = sample_process(s->be, s->sess, s, dir|SMP_OPT_FINAL, arg->expr, NULL);
|
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.curlen, smp, &ctx->frag_ctx.curoff, buf, end);
|
||||||
if (ret == -1 || ctx->frag_ctx.curoff)
|
if (ret == -1 || ctx->frag_ctx.curoff)
|
||||||
goto too_big;
|
goto too_big;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue