You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
3.4 KiB

  1. commit c1620a52a3def02b4837376385c416c03ca874c4
  2. Author: Kevin Zhu <ipandtcp@gmail.com>
  3. Date: Fri Apr 26 14:00:01 2019 +0800
  4. BUG/MEDIUM: spoe: arg len encoded in previous frag frame but len changed
  5. Fragmented arg will do fetch at every encode time, each fetch may get
  6. different result if SMP_F_MAY_CHANGE, for example res.payload, but
  7. the length already encoded in first fragment of the frame, that will
  8. cause SPOA decode failed and waste resources.
  9. This patch must be backported to 1.9 and 1.8.
  10. (cherry picked from commit f7f54280c8106e92a55243f5d60f8587e79602d1)
  11. Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
  12. (cherry picked from commit 3a838e526cdbc00ded5362e66f1ef3a441abc3c1)
  13. Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
  14. diff --git a/include/proto/spoe.h b/include/proto/spoe.h
  15. index 002cf7d7..2cdca10b 100644
  16. --- a/include/proto/spoe.h
  17. +++ b/include/proto/spoe.h
  18. @@ -121,7 +121,7 @@ spoe_decode_buffer(char **buf, char *end, char **str, uint64_t *len)
  19. * many bytes has been encoded. If <*off> is zero at the end, it means that all
  20. * data has been encoded. */
  21. static inline int
  22. -spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end)
  23. +spoe_encode_data(unsigned int *len, struct sample *smp, unsigned int *off, char **buf, char *end)
  24. {
  25. char *p = *buf;
  26. int ret;
  27. @@ -183,15 +183,16 @@ spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end)
  28. ret = spoe_encode_frag_buffer(chk->str, chk->len, &p, end);
  29. if (ret == -1)
  30. return -1;
  31. + *len = chk->len;
  32. }
  33. else {
  34. /* The sample has been fragmented, encode remaining data */
  35. - ret = MIN(chk->len - *off, end - p);
  36. + ret = MIN(*len - *off, end - p);
  37. memcpy(p, chk->str + *off, ret);
  38. p += ret;
  39. }
  40. /* Now update <*off> */
  41. - if (ret + *off != chk->len)
  42. + if (ret + *off != *len)
  43. *off += ret;
  44. else
  45. *off = 0;
  46. diff --git a/include/types/spoe.h b/include/types/spoe.h
  47. index 53e7200c..cfaa42f8 100644
  48. --- a/include/types/spoe.h
  49. +++ b/include/types/spoe.h
  50. @@ -304,6 +304,7 @@ struct spoe_context {
  51. struct spoe_message *curmsg; /* SPOE message from which to resume encoding */
  52. struct spoe_arg *curarg; /* SPOE arg in <curmsg> from which to resume encoding */
  53. unsigned int curoff; /* offset in <curarg> from which to resume encoding */
  54. + unsigned int curlen; /* length of <curarg> need to be encode, for SMP_F_MAY_CHANGE data */
  55. unsigned int flags; /* SPOE_FRM_FL_* */
  56. } frag_ctx; /* Info about fragmented frames, valid on if SPOE_CTX_FL_FRAGMENTED is set */
  57. };
  58. diff --git a/src/flt_spoe.c b/src/flt_spoe.c
  59. index f6109778..0c0b3794 100644
  60. --- a/src/flt_spoe.c
  61. +++ b/src/flt_spoe.c
  62. @@ -2172,6 +2172,7 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx,
  63. list_for_each_entry(arg, &msg->args, list) {
  64. ctx->frag_ctx.curarg = arg;
  65. ctx->frag_ctx.curoff = UINT_MAX;
  66. + ctx->frag_ctx.curlen = 0;
  67. encode_argument:
  68. if (ctx->frag_ctx.curoff != UINT_MAX)
  69. @@ -2186,7 +2187,7 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx,
  70. /* Fetch the arguement value */
  71. smp = sample_process(s->be, s->sess, s, dir|SMP_OPT_FINAL, arg->expr, NULL);
  72. - ret = spoe_encode_data(smp, &ctx->frag_ctx.curoff, buf, end);
  73. + ret = spoe_encode_data(&ctx->frag_ctx.curlen, smp, &ctx->frag_ctx.curoff, buf, end);
  74. if (ret == -1 || ctx->frag_ctx.curoff)
  75. goto too_big;
  76. }