Hi Christopher, Thanks for merging the tcpcheck fix. Here is a v2 of the two other patches, which should now cover all the cases, against current master (64d597032b).
1/2 BUG/MINOR: mjson: fix overreads on truncated JSON paths Besides the trailing backslash of v1, an array index without its closing ']' also makes mjson_get_cb() read past the end of the path: "$[0", "$[" and "$[]" through the fixed 3-character skip, and "$[1" or "$.a[1" through the unbounded search for ']'. Both searches now stop at the end of the string, as upstream mjson does since 2021. The fix is in the walker, so it covers json_query, jwt_header_query, jwt_payload_query and the other mjson callers. I can also reject such paths in sample_check_json_query() if you prefer. 2/2 BUG/MINOR: stick-table: reject invalid gpc/gpt array indexes v1 only rejected negative indexes in the sc-* actions and on the CLI. v2 checks the documented range (0 to 99) wherever an index is parsed: the sc-inc-gpc, sc-set-gpt and sc-add-gpc actions, the CLI data.gpc[]/data.gpt[] names, and the 16 fetches and converters taking an index (sc_get_gpc, src_get_gpt, table_gpc...), through a shared argument check. Indexes above UINT_MAX were truncated, e.g. sc-inc-gpc(4294967296,0) incremented gpc[0]. The CLI table filters now also reject an index beyond the table's array, like "set table". Tested with a release build (TARGET=linux-glibc USE_OPENSSL=1 USE_PCRE2=1 USE_ZLIB=1, no warnings) and an ASan+UBSan build. On master, json_query and jwt_header_query report a heap-buffer-overflow READ in plen1() or mjson_get_cb() for the truncated paths. With the patch there is no report and well-formed paths give the same results. Each of the 19 index keywords is rejected with -1, 100 and 4294967296 and accepted with 0 and 99, and a valid configuration gives the same counters at runtime. "haproxy -c" gives the same result before and after on the examples/ configs and on the 416 configs embedded in the reg-tests, including sc_gpc_gpt, json_query and the jwt ones. I still could not run the reg-tests themselves. The patches are attached (git format-patch -v2). As for v1, these were found with an LLM-Enhanced Static Analysis Engine and verified manually. Martin Mirchev On Fri, Nov 06, 2026 05:05 AM, Christopher Faulet <[email protected]> wrote: > Le 30/10/2026 à 6:39 AM, Martin Mirchev a écrit : > > Hi, > > > > Here are three small independent fixes against current master > > (e5e52e33c). All three are about values from the configuration or the > > CLI that were not checked. The patches are attached (git format-patch). > > > > 1/3 BUG/MINOR: tcpcheck: check the number of "hdr" in http-check send > > The headers of an "http-check send" rule go into a stack array sized > > by tune.http.maxhdr plus a terminator, without any bounds check. > > With "tune.http.maxhdr 5" and five "hdr" arguments, "haproxy -c" > > segfaults on a release build (ASan: dynamic-stack-buffer-overflow > > WRITE). The default of 101 cannot be reached because of the 64-word > > line limit. The rule is now rejected with "too many headers". > > Backport to all stable versions (since 2.2). > > > > 2/3 BUG/MINOR: mjson: fix overread on a path ending with a backslash > > plen1()/plen2() skip two characters on a backslash, so a json_query > > path ending with one, e.g. json_query($.a\\), makes them read past > > the trailing zero. ASan reports a heap-buffer-overflow READ in plen1() > > on the first request. The upstream mjson code has the same bug. > > Backport to all stable versions (since 2.4). > > > > 3/3 BUG/MINOR: stick-table: reject negative gpc/gpt array indexes > > strtoul() accepts "-1" and wraps it, so data.gpc[-1] on the CLI and > > sc-inc-gpc(-1,0)/sc-set-gpt(-1,0)/sc-add-gpc(-1,0) in the config are > > accepted and then silently do nothing or fail as "index out of range". > > There is no memory issue, since the index is checked before use. This > > is the index counterpart of 1f1b701fe3. Backport to all stable > > versions, the CLI part only to 3.2 and above. > > > > Tested on e5e52e33c with an ASan+UBSan build and a release build > > (USE_OPENSSL=1 USE_PCRE2=1 USE_ZLIB=1). On master, the reproducers for > > 1/3 and 2/3 trigger the ASan reports above (1/3 also segfaults on the > > release build), and the invalid indexes of 3/3 are accepted. With the > > patches, 1/3 and 3/3 give a config or CLI error, and 2/3 returns an > > empty result with no ASan report. Paths with escaped separators > > ($.my\\.key) and array indexes still work. "haproxy -c" gives the same > > result before and after on the examples/ configs and on the configs > > embedded in the checks, stick-table, stickiness, converter and > > sample_fetches reg-tests. I could not run the reg-tests themselves > > because I do not have vtest here. > > > > These were found with an LLM-Enhanced Static Analysis Engine and > verified manually. > > > > Martin Mirchev > > Thanks, I merged the patch about the tcpcheck. Others seem valid too but > don't > cover all cases. I must still review them deeper. > > -- > Christopher Faulet > >
From 1ddbaf0522586278b550bd2a33978f348c4e7daa Mon Sep 17 00:00:00 2001 From: Martin Mirchev <[email protected]> Date: Fri, 6 Nov 2026 08:54:56 +0800 Subject: [PATCH v2 1/2] BUG/MINOR: mjson: fix overreads on truncated JSON paths The mjson path walker reads past the end of the path in three places when the path is truncated: - plen1() and plen2() measure a key segment and skip two characters when they see a backslash, so that an escaped '.' or '[' is not taken as a separator. When the path ends with a backslash, the second skipped character is the trailing zero and the loop goes on reading past the end of the string (e.g. "$.a\"). - in mjson_get_cb(), when an array is entered and the requested index is 0, the path position is advanced by 3 characters, assuming the index is written "[0]". With "$[0", "$[" or "$[]", this goes past the trailing zero. - when the element at a non-zero index is reached, the closing ']' is looked for without checking for the trailing zero, so with "$[1" or "$.a[1" the loop reads until it finds a ']' somewhere in memory. The path comes from the json_query converter's argument (and from the jwt_header_query and jwt_payload_query ones), which is stored in an exactly sized allocation and is not checked beyond being non-empty. With: http-request set-var(txn.out) req.fhdr(json),json_query($.a\\) (the config parser turns "\\" into "\", so the path is "$.a\"), or with json_query('$.a[1') and a request carrying {"a":[1,2]}, ASan reports a heap-buffer-overflow READ in plen1() or mjson_get_cb() called from sample_conv_json_query(). Let's only skip the character following a backslash when it is not the end of the string, and make both searches for the closing ']' stop at the end of the string and only skip the ']' if it was found. The latter is what the upstream mjson project does since its commit d2d9e46 ("Fix #32 - fail search if value not found in the requested array elem"); the backslash case is still present there. Well-formed paths are not affected, except that an index written with leading zeroes such as "[00]" now selects the element instead of never matching. A truncated index such as "$.a[1" now behaves as if the ']' was present, which is also what upstream mjson does. This should be backported to all stable versions. The code came with mjson in 2.4. --- src/mjson.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/mjson.c b/src/mjson.c index 603947d..13405ca 100644 --- a/src/mjson.c +++ b/src/mjson.c @@ -176,7 +176,7 @@ struct msjon_get_data { static int plen1(const char *s) { int i = 0, n = 0; while (s[i] != '\0' && s[i] != '.' && s[i] != '[') - n++, i += s[i] == '\\' ? 2 : 1; + n++, i += (s[i] == '\\' && s[i + 1] != '\0') ? 2 : 1; // printf("PLEN: s: [%s], [%.*s] => %d\n", s, i, s, n); return n; } @@ -184,7 +184,7 @@ static int plen1(const char *s) { static int plen2(const char *s) { int i = 0, __attribute__((unused)) n = 0; while (s[i] != '\0' && s[i] != '.' && s[i] != '[') - n++, i += s[i] == '\\' ? 2 : 1; + n++, i += (s[i] == '\\' && s[i + 1] != '\0') ? 2 : 1; // printf("PLEN: s: [%s], [%.*s] => %d\n", s, i, s, n); return i; } @@ -215,7 +215,8 @@ static int mjson_get_cb(int tok, const char *s, int off, int len, void *ud) { data->i2 = (int) mystrtod(&data->path[data->pos + 1], strlen(&data->path[data->pos + 1]), NULL); if (data->i1 == data->i2) { data->d2++; - data->pos += 3; + while (data->path[data->pos] && data->path[data->pos] != ']') data->pos++; + if (data->path[data->pos] == ']') data->pos++; } } if (!data->path[data->pos] && data->d1 == data->d2) data->obj = off; @@ -224,8 +225,8 @@ static int mjson_get_cb(int tok, const char *s, int off, int len, void *ud) { if (data->d1 == data->d2 + 1) { data->i1++; if (data->i1 == data->i2) { - while (data->path[data->pos] != ']') data->pos++; - data->pos++; + while (data->path[data->pos] && data->path[data->pos] != ']') data->pos++; + if (data->path[data->pos] == ']') data->pos++; data->d2++; } } -- 2.50.1
From f161a6f8151895ad9ae3cf747e611d744487f685 Mon Sep 17 00:00:00 2001 From: Martin Mirchev <[email protected]> Date: Fri, 6 Nov 2026 09:02:11 +0800 Subject: [PATCH v2 2/2] BUG/MINOR: stick-table: reject invalid gpc/gpt array indexes The index of the gpc, gpc_rate and gpt arrays is never checked where it is parsed, so invalid values are silently accepted: - the sc-inc-gpc, sc-set-gpt and sc-add-gpc actions parse it with strtoul(), which accepts a sign and wraps "-1" to UINT_MAX, and which returns 0 for an empty index, so "sc-inc-gpc(,0)" updates gpc[0]. Values of 100 and above are accepted as well. - the sample fetches and converters taking an index (sc_get_gpc, sc_get_gpt, sc_gpc_rate, sc_inc_gpc, sc_clr_gpc, sc1_clr_gpc and the src_* and table_* variants) take it as a signed integer without any check, so sc_get_gpc(-1,0) or table_gpc(100,t) pass "haproxy -c" and never return anything. - on the CLI, "data.gpc[-1]" is taken as index 4294967295, so "set table" reports "index out of range in this data array" instead of rejecting the name as for "data.gpc[q]", and the "show table" and "clear table" filters accept it and match no entry, as they do for any index beyond the table's array. Since the index is stored as an unsigned int, values above UINT_MAX are even truncated: "sc-inc-gpc(4294967296,0)" increments gpc[0] and sc_get_gpc(4294967296,0) returns gpc[0], and the same happens on the CLI. There is no memory access issue since stktable_data_ptr_idx() checks the index against the array size before use, but these errors should be reported where the index is parsed. The documentation states that <idx> is an integer between 0 and 99, which is STKTABLE_MAX_DT_ARRAY_SIZE - 1. This patch adds stktable_parse_array_idx(), which requires the index to start with a digit and to be lower than STKTABLE_MAX_DT_ARRAY_SIZE, and uses it in stktable_get_data_type_idx() and in the three action parsers. The fetches and converters get a new argument check function which does the same verification on their first argument. Finally, the CLI table filters now reject an index beyond the array size of the table, as "set table" already does. The table is not known when the actions, fetches and converters are parsed, so they can only be checked against the maximum array size. This is the index counterpart of commit 1f1b701fe3 ("BUG/MINOR: stick-table: reject negative stick counter IDs in sc-* actions"). Configurations using an invalid index are now rejected, but such an index never worked, or silently used gpc[0]/gpt[0]. This should be backported to all stable versions where the gpc/gpt arrays exist (2.5 and above). The CLI parts only apply to 3.2 and above where stktable_get_data_type_idx() was added, and sc-add-gpc() appeared in 2.8. --- src/stick_table.c | 100 +++++++++++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 27 deletions(-) diff --git a/src/stick_table.c b/src/stick_table.c index dbb59f7..dbfba8c 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -1967,6 +1967,25 @@ int stktable_get_data_type(char *name) return -1; } +/* Parses the gpc/gpt array index at the beginning of <str>. It must start + * with a digit and be lower than STKTABLE_MAX_DT_ARRAY_SIZE. On success, the + * index is stored into <idx> and 1 is returned. Otherwise 0 is returned. In + * both cases <end> is set to the first character after the parsed digits. + */ +static int stktable_parse_array_idx(const char *str, char **end, unsigned int *idx) +{ + unsigned long val; + + *end = (char *)str; + if (!isdigit((unsigned char)*str)) + return 0; // also rejects the sign and spaces strtoul() accepts + val = strtoul(str, end, 10); + if (val >= STKTABLE_MAX_DT_ARRAY_SIZE) + return 0; + *idx = val; + return 1; +} + /* * Same as stktable_get_data_type() but also expects optional index after the * name in the form "name[idx]", but only for array types @@ -1996,8 +2015,7 @@ int stktable_get_data_type_idx(char *name, unsigned int *idx) /* we've got a match */ name += stop + 1; - *idx = strtoul(name, &ret, 10); - if (ret == name || *ret != ']') + if (!stktable_parse_array_idx(name, &ret, idx) || *ret != ']') return -1; // bad value if (ret[1]) return -1; // unexpected data @@ -2901,9 +2919,9 @@ static enum act_parse_ret parse_inc_gpc(const char **args, int *arg, struct prox cmd_name += strlen("sc-inc-gpc"); if (*cmd_name == '(') { cmd_name++; /* skip the '(' */ - rule->arg.gpc.idx = strtoul(cmd_name, &error, 10); /* Convert stick table id. */ - if (*error != ',') { - memprintf(err, "Missing gpc ID '%s'. Expects sc-inc-gpc(<GPC ID>,<Track ID>)", args[*arg-1]); + if (!stktable_parse_array_idx(cmd_name, &error, &rule->arg.gpc.idx) || *error != ',') { + memprintf(err, "Missing or invalid gpc ID '%s'. Expects sc-inc-gpc(<GPC ID>,<Track ID>) with <GPC ID> between 0 and %d", + args[*arg-1], STKTABLE_MAX_DT_ARRAY_SIZE - 1); return ACT_RET_PRS_ERR; } else { @@ -3131,9 +3149,9 @@ static enum act_parse_ret parse_set_gpt(const char **args, int *arg, struct prox cmd_name += strlen("sc-set-gpt"); if (*cmd_name == '(') { cmd_name++; /* skip the '(' */ - rule->arg.gpt.idx = strtoul(cmd_name, &error, 10); /* Convert stick table id. */ - if (*error != ',') { - memprintf(err, "Missing gpt ID '%s'. Expects sc-set-gpt(<GPT ID>,<Track ID>)", args[*arg-1]); + if (!stktable_parse_array_idx(cmd_name, &error, &rule->arg.gpt.idx) || *error != ',') { + memprintf(err, "Missing or invalid gpt ID '%s'. Expects sc-set-gpt(<GPT ID>,<Track ID>) with <GPT ID> between 0 and %d", + args[*arg-1], STKTABLE_MAX_DT_ARRAY_SIZE - 1); return ACT_RET_PRS_ERR; } else { @@ -3324,9 +3342,9 @@ static enum act_parse_ret parse_add_gpc(const char **args, int *arg, struct prox return ACT_RET_PRS_ERR; } cmd_name++; /* skip the '(' */ - rule->arg.gpc.idx = strtoul(cmd_name, &error, 10); /* Convert stick table id. */ - if (*error != ',') { - memprintf(err, "Missing gpc ID. Expects %s(<GPC ID>,<Track ID>)", args[*arg-1]); + if (!stktable_parse_array_idx(cmd_name, &error, &rule->arg.gpc.idx) || *error != ',') { + memprintf(err, "Missing or invalid gpc ID. Expects %s(<GPC ID>,<Track ID>) with <GPC ID> between 0 and %d", + args[*arg-1], STKTABLE_MAX_DT_ARRAY_SIZE - 1); return ACT_RET_PRS_ERR; } else { @@ -5720,6 +5738,10 @@ static int table_prepare_data_request(struct appctx *appctx, char **args) if (!((struct stktable *)ctx->target)->data_ofs[ctx->data_type[i]]) return cli_dynerr(appctx, memprintf(&err, "Filter entry #%i: Data type not stored in this table\n", i + 1)); + if (stktable_data_types[ctx->data_type[i]].is_array && + ctx->data_idx[i] >= ((struct stktable *)ctx->target)->data_nbelem[ctx->data_type[i]]) + return cli_dynerr(appctx, memprintf(&err, "Filter entry #%i: index out of range in this data array\n", i + 1)); + ctx->data_op[i] = get_std_op(args[4+3*i]); if (ctx->data_op[i] < 0) return cli_dynerr(appctx, memprintf(&err, "Filter entry #%i: Require and operator among \"eq\", \"ne\", \"le\", \"ge\", \"lt\", \"gt\"\n", i + 1)); @@ -6144,26 +6166,50 @@ static struct action_kw_list http_after_res_kws = { { }, { INITCALL1(STG_REGISTER, http_after_res_keywords_register, &http_after_res_kws); +/* Checks that the first argument of a sample fetch taking a gpc or gpt array + * index is a valid index, i.e. between 0 and STKTABLE_MAX_DT_ARRAY_SIZE-1. + * Returns 1 if OK, otherwise 0 with an error message in <err>. + */ +static int smp_check_gpc_gpt_idx(struct arg *args, char **err) +{ + if (args[0].type != ARGT_SINT) + return 1; + + if (args[0].data.sint < 0 || args[0].data.sint >= STKTABLE_MAX_DT_ARRAY_SIZE) { + memprintf(err, "invalid array index %lld, must be between 0 and %d", + (long long)args[0].data.sint, STKTABLE_MAX_DT_ARRAY_SIZE - 1); + return 0; + } + return 1; +} + +/* Same as smp_check_gpc_gpt_idx() for converters */ +static int sample_conv_check_gpc_gpt_idx(struct arg *args, struct sample_conv *conv, + const char *file, int line, char **err) +{ + return smp_check_gpc_gpt_idx(args, err); +} + /* Note: must not be declared <const> as its list will be overwritten. * Please take care of keeping this list alphabetically sorted. */ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, { { "sc_bytes_in_rate", smp_fetch_sc_bytes_in_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_bytes_out_rate", smp_fetch_sc_bytes_out_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, - { "sc_clr_gpc", smp_fetch_sc_clr_gpc, ARG3(2,SINT,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, + { "sc_clr_gpc", smp_fetch_sc_clr_gpc, ARG3(2,SINT,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_clr_gpc0", smp_fetch_sc_clr_gpc0, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_clr_gpc1", smp_fetch_sc_clr_gpc1, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN }, { "sc_conn_cnt", smp_fetch_sc_conn_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_conn_cur", smp_fetch_sc_conn_cur, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_conn_rate", smp_fetch_sc_conn_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, - { "sc_get_gpt", smp_fetch_sc_get_gpt, ARG3(2,SINT,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, + { "sc_get_gpt", smp_fetch_sc_get_gpt, ARG3(2,SINT,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_get_gpt0", smp_fetch_sc_get_gpt0, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, - { "sc_get_gpc", smp_fetch_sc_get_gpc, ARG3(2,SINT,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, + { "sc_get_gpc", smp_fetch_sc_get_gpc, ARG3(2,SINT,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_get_gpc0", smp_fetch_sc_get_gpc0, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_get_gpc1", smp_fetch_sc_get_gpc1, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN }, { "sc_glitch_cnt", smp_fetch_sc_glitch_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_glitch_rate", smp_fetch_sc_glitch_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, - { "sc_gpc_rate", smp_fetch_sc_gpc_rate, ARG3(2,SINT,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, + { "sc_gpc_rate", smp_fetch_sc_gpc_rate, ARG3(2,SINT,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_gpc0_rate", smp_fetch_sc_gpc0_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, @@ -6172,7 +6218,7 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, { { "sc_http_fail_rate", smp_fetch_sc_http_fail_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_http_req_cnt", smp_fetch_sc_http_req_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_http_req_rate", smp_fetch_sc_http_req_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, - { "sc_inc_gpc", smp_fetch_sc_inc_gpc, ARG3(2,SINT,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, + { "sc_inc_gpc", smp_fetch_sc_inc_gpc, ARG3(2,SINT,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_inc_gpc0", smp_fetch_sc_inc_gpc0, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_inc_gpc1", smp_fetch_sc_inc_gpc1, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_kbytes_in", smp_fetch_sc_kbytes_in, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, @@ -6213,7 +6259,7 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, { { "sc0_trackers", smp_fetch_sc_trackers, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc1_bytes_in_rate", smp_fetch_sc_bytes_in_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc1_bytes_out_rate", smp_fetch_sc_bytes_out_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, - { "sc1_clr_gpc", smp_fetch_sc_clr_gpc, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, + { "sc1_clr_gpc", smp_fetch_sc_clr_gpc, ARG2(1,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_INTRN, }, { "sc1_clr_gpc0", smp_fetch_sc_clr_gpc0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc1_clr_gpc1", smp_fetch_sc_clr_gpc1, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc1_conn_cnt", smp_fetch_sc_conn_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, @@ -6272,20 +6318,20 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, { { "sc2_trackers", smp_fetch_sc_trackers, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "src_bytes_in_rate", smp_fetch_sc_bytes_in_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_bytes_out_rate", smp_fetch_sc_bytes_out_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, - { "src_clr_gpc", smp_fetch_sc_clr_gpc, ARG2(2,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, + { "src_clr_gpc", smp_fetch_sc_clr_gpc, ARG2(2,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_clr_gpc0", smp_fetch_sc_clr_gpc0, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_clr_gpc1", smp_fetch_sc_clr_gpc1, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_conn_cnt", smp_fetch_sc_conn_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_conn_cur", smp_fetch_sc_conn_cur, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_conn_rate", smp_fetch_sc_conn_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, - { "src_get_gpt" , smp_fetch_sc_get_gpt, ARG2(2,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, + { "src_get_gpt" , smp_fetch_sc_get_gpt, ARG2(2,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_get_gpt0", smp_fetch_sc_get_gpt0, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, - { "src_get_gpc", smp_fetch_sc_get_gpc, ARG2(2,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, + { "src_get_gpc", smp_fetch_sc_get_gpc, ARG2(2,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_get_gpc0", smp_fetch_sc_get_gpc0, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_get_gpc1", smp_fetch_sc_get_gpc1, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_glitch_cnt", smp_fetch_sc_glitch_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_glitch_rate", smp_fetch_sc_glitch_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, - { "src_gpc_rate", smp_fetch_sc_gpc_rate, ARG2(2,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, + { "src_gpc_rate", smp_fetch_sc_gpc_rate, ARG2(2,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_gpc0_rate", smp_fetch_sc_gpc0_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, @@ -6294,7 +6340,7 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, { { "src_http_fail_rate", smp_fetch_sc_http_fail_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_http_req_cnt", smp_fetch_sc_http_req_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_http_req_rate", smp_fetch_sc_http_req_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, - { "src_inc_gpc", smp_fetch_sc_inc_gpc, ARG2(2,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, + { "src_inc_gpc", smp_fetch_sc_inc_gpc, ARG2(2,SINT,TAB), smp_check_gpc_gpt_idx, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_inc_gpc0", smp_fetch_sc_inc_gpc0, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_inc_gpc1", smp_fetch_sc_inc_gpc1, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_kbytes_in", smp_fetch_sc_kbytes_in, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, @@ -6314,19 +6360,19 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, { { "in_table", sample_conv_in_table, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_BOOL }, { "table_bytes_in_rate", sample_conv_table_bytes_in_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_bytes_out_rate", sample_conv_table_bytes_out_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, - { "table_clr_gpc", sample_conv_table_clr_gpc, ARG2(2,SINT,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, + { "table_clr_gpc", sample_conv_table_clr_gpc, ARG2(2,SINT,TAB), sample_conv_check_gpc_gpt_idx, SMP_T_ANY, SMP_T_SINT }, { "table_clr_gpc0", sample_conv_table_clr_gpc0, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_clr_gpc1", sample_conv_table_clr_gpc1, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_conn_cnt", sample_conv_table_conn_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_conn_cur", sample_conv_table_conn_cur, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_conn_rate", sample_conv_table_conn_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_expire", sample_conv_table_expire, ARG2(1,TAB,SINT), NULL, SMP_T_ANY, SMP_T_SINT }, - { "table_gpt", sample_conv_table_gpt, ARG2(2,SINT,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, + { "table_gpt", sample_conv_table_gpt, ARG2(2,SINT,TAB), sample_conv_check_gpc_gpt_idx, SMP_T_ANY, SMP_T_SINT }, { "table_gpt0", sample_conv_table_gpt0, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, - { "table_gpc", sample_conv_table_gpc, ARG2(2,SINT,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, + { "table_gpc", sample_conv_table_gpc, ARG2(2,SINT,TAB), sample_conv_check_gpc_gpt_idx, SMP_T_ANY, SMP_T_SINT }, { "table_gpc0", sample_conv_table_gpc0, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_gpc1", sample_conv_table_gpc1, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, - { "table_gpc_rate", sample_conv_table_gpc_rate, ARG2(2,SINT,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, + { "table_gpc_rate", sample_conv_table_gpc_rate, ARG2(2,SINT,TAB), sample_conv_check_gpc_gpt_idx, SMP_T_ANY, SMP_T_SINT }, { "table_gpc0_rate", sample_conv_table_gpc0_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_gpc1_rate", sample_conv_table_gpc1_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_glitch_cnt", sample_conv_table_glitch_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, @@ -6338,7 +6384,7 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, { { "table_http_req_cnt", sample_conv_table_http_req_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_http_req_rate", sample_conv_table_http_req_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_idle", sample_conv_table_idle, ARG2(1,TAB,SINT), NULL, SMP_T_ANY, SMP_T_SINT }, - { "table_inc_gpc", sample_conv_table_inc_gpc, ARG2(2,SINT,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, + { "table_inc_gpc", sample_conv_table_inc_gpc, ARG2(2,SINT,TAB), sample_conv_check_gpc_gpt_idx, SMP_T_ANY, SMP_T_SINT }, { "table_inc_gpc0", sample_conv_table_inc_gpc0, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_inc_gpc1", sample_conv_table_inc_gpc1, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_kbytes_in", sample_conv_table_kbytes_in, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, -- 2.50.1

