]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: spoe: arg len encoded in previous frag frame but len changed
authorKevin Zhu <ipandtcp@gmail.com>
Fri, 26 Apr 2019 06:00:01 +0000 (14:00 +0800)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 29 Apr 2019 14:02:05 +0000 (16:02 +0200)
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.

include/proto/spoe.h
include/types/spoe.h
src/flt_spoe.c

index e5b3b4b2c30b7407cb77dc9066e5c86d009cbd48..86328adef1c4c134fc0493559bcef2004676542a 100644 (file)
@@ -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;
index a744cd7b8174dfe88b950d19f0811be09e5e5377..9bba492b5416b57d95065ae36ebe0ae57c3fc736 100644 (file)
@@ -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         curlen;      /* 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 */
 
index 63d40a6fd7cdeba4111345b3f2b9de30b3581782..609fa306f14b534ad0ab2d387c501796f47aad6f 100644 (file)
@@ -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.curlen, smp, &ctx->frag_ctx.curoff, buf, end);
                if (ret == -1 || ctx->frag_ctx.curoff)
                        goto too_big;
        }