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.

171 lines
5.0 KiB

  1. From 06170c50ae5cd0fb23510b832826f7e63a5a8894 Mon Sep 17 00:00:00 2001
  2. From: Thierry FOURNIER <tfournier@haproxy.com>
  3. Date: Mon, 16 Mar 2015 23:23:53 +0100
  4. Subject: [PATCH 7/9] BUG/MEDIUM: http: the function "(req|res)-replace-value"
  5. doesn't respect the HTTP syntax
  6. These function used an invalid header parser.
  7. - The trailing white-spaces were embedded in the replacement regex,
  8. - The double-quote (") containing comma (,) were not respected.
  9. This patch replace this parser by the "official" parser http_find_header2().
  10. (cherry picked from commit 191f9efdc58f21af1d9dde3db5ba198d7f1ce22e)
  11. ---
  12. src/proto_http.c | 126 +++++++++++++++----------------------------------------
  13. 1 file changed, 34 insertions(+), 92 deletions(-)
  14. diff --git a/src/proto_http.c b/src/proto_http.c
  15. index f53b5e2..c49c4f4 100644
  16. --- a/src/proto_http.c
  17. +++ b/src/proto_http.c
  18. @@ -3179,113 +3179,55 @@ static inline void inet_set_tos(int fd, struct sockaddr_storage from, int tos)
  19. #endif
  20. }
  21. -/* Returns the number of characters written to destination,
  22. - * -1 on internal error and -2 if no replacement took place.
  23. - */
  24. -static int http_replace_header(struct my_regex *re, char *dst, uint dst_size, char *val, int len,
  25. - const char *rep_str)
  26. -{
  27. - if (!regex_exec_match2(re, val, len, MAX_MATCH, pmatch))
  28. - return -2;
  29. -
  30. - return exp_replace(dst, dst_size, val, rep_str, pmatch);
  31. -}
  32. -
  33. -/* Returns the number of characters written to destination,
  34. - * -1 on internal error and -2 if no replacement took place.
  35. - */
  36. -static int http_replace_value(struct my_regex *re, char *dst, uint dst_size, char *val, int len, char delim,
  37. - const char *rep_str)
  38. -{
  39. - char* p = val;
  40. - char* dst_end = dst + dst_size;
  41. - char* dst_p = dst;
  42. -
  43. - for (;;) {
  44. - char *p_delim;
  45. -
  46. - /* look for delim. */
  47. - p_delim = p;
  48. - while (p_delim < val + len && *p_delim != delim)
  49. - p_delim++;
  50. -
  51. - if (regex_exec_match2(re, p, p_delim-p, MAX_MATCH, pmatch)) {
  52. - int replace_n = exp_replace(dst_p, dst_end - dst_p, p, rep_str, pmatch);
  53. -
  54. - if (replace_n < 0)
  55. - return -1;
  56. -
  57. - dst_p += replace_n;
  58. - } else {
  59. - uint len = p_delim - p;
  60. -
  61. - if (dst_p + len >= dst_end)
  62. - return -1;
  63. -
  64. - memcpy(dst_p, p, len);
  65. - dst_p += len;
  66. - }
  67. -
  68. - if (dst_p >= dst_end)
  69. - return -1;
  70. -
  71. - /* end of the replacements. */
  72. - if (p_delim >= val + len)
  73. - break;
  74. -
  75. - /* Next part. */
  76. - *dst_p++ = delim;
  77. - p = p_delim + 1;
  78. - }
  79. -
  80. - return dst_p - dst;
  81. -}
  82. -
  83. static int http_transform_header(struct session* s, struct http_msg *msg, const char* name, uint name_len,
  84. char* buf, struct hdr_idx* idx, struct list *fmt, struct my_regex *re,
  85. struct hdr_ctx* ctx, int action)
  86. {
  87. + int (*http_find_hdr_func)(const char *name, int len, char *sol,
  88. + struct hdr_idx *idx, struct hdr_ctx *ctx);
  89. + struct chunk *replace = get_trash_chunk();
  90. + struct chunk *output = get_trash_chunk();
  91. +
  92. + replace->len = build_logline(s, replace->str, replace->size, fmt);
  93. + if (replace->len >= replace->size - 1)
  94. + return -1;
  95. +
  96. ctx->idx = 0;
  97. - while (http_find_full_header2(name, name_len, buf, idx, ctx)) {
  98. + /* Choose the header browsing function. */
  99. + switch (action) {
  100. + case HTTP_REQ_ACT_REPLACE_VAL:
  101. + case HTTP_RES_ACT_REPLACE_VAL:
  102. + http_find_hdr_func = http_find_header2;
  103. + break;
  104. + case HTTP_REQ_ACT_REPLACE_HDR:
  105. + case HTTP_RES_ACT_REPLACE_HDR:
  106. + http_find_hdr_func = http_find_full_header2;
  107. + break;
  108. + default: /* impossible */
  109. + return -1;
  110. + }
  111. +
  112. + while (http_find_hdr_func(name, name_len, buf, idx, ctx)) {
  113. struct hdr_idx_elem *hdr = idx->v + ctx->idx;
  114. int delta;
  115. - char* val = (char*)ctx->line + ctx->val;
  116. - char* val_end = (char*)ctx->line + hdr->len;
  117. - char* reg_dst_buf;
  118. - uint reg_dst_buf_size;
  119. - int n_replaced;
  120. -
  121. - trash.len = build_logline(s, trash.str, trash.size, fmt);
  122. -
  123. - if (trash.len >= trash.size - 1)
  124. - return -1;
  125. + char *val = ctx->line + ctx->val;
  126. + char* val_end = val + ctx->vlen;
  127. - reg_dst_buf = trash.str + trash.len + 1;
  128. - reg_dst_buf_size = trash.size - trash.len - 1;
  129. + if (!regex_exec_match2(re, val, val_end-val, MAX_MATCH, pmatch))
  130. + continue;
  131. - switch (action) {
  132. - case HTTP_REQ_ACT_REPLACE_VAL:
  133. - case HTTP_RES_ACT_REPLACE_VAL:
  134. - n_replaced = http_replace_value(re, reg_dst_buf, reg_dst_buf_size, val, val_end-val, ',', trash.str);
  135. - break;
  136. - case HTTP_REQ_ACT_REPLACE_HDR:
  137. - case HTTP_RES_ACT_REPLACE_HDR:
  138. - n_replaced = http_replace_header(re, reg_dst_buf, reg_dst_buf_size, val, val_end-val, trash.str);
  139. - break;
  140. - default: /* impossible */
  141. + output->len = exp_replace(output->str, output->size, val, replace->str, pmatch);
  142. + if (output->len == -1)
  143. return -1;
  144. - }
  145. - switch (n_replaced) {
  146. - case -1: return -1;
  147. - case -2: continue;
  148. - }
  149. -
  150. - delta = buffer_replace2(msg->chn->buf, val, val_end, reg_dst_buf, n_replaced);
  151. + delta = buffer_replace2(msg->chn->buf, val, val_end, output->str, output->len);
  152. hdr->len += delta;
  153. http_msg_move_end(msg, delta);
  154. +
  155. + /* Adjust the length of the current value of the index. */
  156. + ctx->vlen += delta;
  157. }
  158. return 0;
  159. --
  160. 2.0.5