From bfa5f60ad827544933b9f4c5d72d56834739b530 Mon Sep 17 00:00:00 2001 From: michaelortmann <41313082+michaelortmann@users.noreply.github.com> Date: Fri, 12 Oct 2018 05:38:55 +0200 Subject: [PATCH] Fix information leak through TCL variables. Fixes #137. Fixes #414 Found by: maimizuno Patch by: michaelortmann --- src/tclhash.c | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/tclhash.c b/src/tclhash.c index 61df2b5b5..555cf1675 100644 --- a/src/tclhash.c +++ b/src/tclhash.c @@ -817,6 +817,7 @@ int check_tcl_bind(tcl_bind_list_t *tl, const char *match, char *proc = NULL, *mask = NULL; tcl_bind_mask_t *tm, *tm_last = NULL, *tm_p = NULL; tcl_cmd_t *tc, *htc = NULL; + char *str, *varName, *brkt; for (tm = tl->first; tm && !finish; tm_last = tm, tm = tm->next) { @@ -873,7 +874,7 @@ int check_tcl_bind(tcl_bind_list_t *tl, const char *match, if (match_type & BIND_ALTER_ARGS) { if (tcl_resultempty()) - return x; + goto finally; } else if ((match_type & BIND_STACKRET) && x == BIND_EXEC_LOG) { /* If we have multiple commands/triggers, and if any of the * commands return 1, we store the result so we can return it @@ -884,30 +885,38 @@ int check_tcl_bind(tcl_bind_list_t *tl, const char *match, continue; } else if ((match_type & BIND_WANTRET) && x == BIND_EXEC_LOG) /* Return immediately if any commands return 1 */ - return x; + goto finally; } } } } - if (!cnt) - return BIND_NOMATCH; + if (!cnt) { + x = BIND_NOMATCH; + goto finally; + } /* Do this before updating the preferred entries information, * since we don't want to change the order of stacked binds */ - if (result) /* BIND_STACKRET */ - return result; + if (result) { /* BIND_STACKRET */ + x = result; + goto finally; + } - if ((match_type & 0x07) == MATCH_MASK || (match_type & 0x07) == MATCH_CASE) - return BIND_EXECUTED; + if ((match_type & 0x07) == MATCH_MASK || (match_type & 0x07) == MATCH_CASE) { + x = BIND_EXECUTED; + goto finally; + } /* Hit counter */ if (htc) htc->hits++; - if (cnt > 1) - return BIND_AMBIGUOUS; + if (cnt > 1) { + x = BIND_AMBIGUOUS; + goto finally; + } /* Now that we have found exactly one bind, we can update the * preferred entries information. @@ -923,7 +932,21 @@ int check_tcl_bind(tcl_bind_list_t *tl, const char *match, tl->first = tm; } - return trigger_bind(proc, param, mask); + x = trigger_bind(proc, param, mask); + +finally: + str = nmalloc(strlen(param) + 1); + strcpy(str, param); + + for (varName = strtok_r(str, " $:", &brkt); + varName; + varName = strtok_r(NULL, " $:", &brkt)) + { + Tcl_UnsetVar(interp, varName, 0); + } + + nfree(str); + return x; }