| To: vim-dev@vim.org |
| Subject: patch 7.0.183 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=ISO-8859-1 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.0.183 |
| Problem: Crash in ":let" when redirecting to a variable that's being |
| displayed. (Thomas Link) |
| Solution: When redirecting to a variable only do the assignment when |
| stopping redirection to avoid that setting the variable causes a |
| freed string to be accessed. |
| Files: src/eval.c |
| |
| |
| |
| |
| |
| *** 898,903 **** |
| --- 898,904 ---- |
| } |
| |
| static lval_T *redir_lval = NULL; |
| + static garray_T redir_ga; /* only valid when redir_lval is not NULL */ |
| static char_u *redir_endp = NULL; |
| static char_u *redir_varname = NULL; |
| |
| |
| *** 932,937 **** |
| --- 933,941 ---- |
| return FAIL; |
| } |
| |
| + /* The output is stored in growarray "redir_ga" until redirection ends. */ |
| + ga_init2(&redir_ga, (int)sizeof(char), 500); |
| + |
| /* Parse the variable name (can be a dict or list entry). */ |
| redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE, |
| FNE_CHECK_START); |
| |
| *** 974,1015 **** |
| } |
| |
| /* |
| ! * Append "value[len]" to the variable set by var_redir_start(). |
| */ |
| void |
| ! var_redir_str(value, len) |
| char_u *value; |
| ! int len; |
| { |
| ! char_u *val; |
| ! typval_T tv; |
| ! int save_emsg; |
| ! int err; |
| |
| if (redir_lval == NULL) |
| return; |
| |
| ! if (len == -1) |
| ! /* Append the entire string */ |
| ! val = vim_strsave(value); |
| ! else |
| ! /* Append only the specified number of characters */ |
| ! val = vim_strnsave(value, len); |
| ! if (val == NULL) |
| ! return; |
| ! |
| ! tv.v_type = VAR_STRING; |
| ! tv.vval.v_string = val; |
| |
| ! save_emsg = did_emsg; |
| ! did_emsg = FALSE; |
| ! set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)"."); |
| ! err = did_emsg; |
| ! did_emsg |= save_emsg; |
| ! if (err) |
| var_redir_stop(); |
| - |
| - vim_free(tv.vval.v_string); |
| } |
| |
| /* |
| --- 978,1013 ---- |
| } |
| |
| /* |
| ! * Append "value[value_len]" to the variable set by var_redir_start(). |
| ! * The actual appending is postponed until redirection ends, because the value |
| ! * appended may in fact be the string we write to, changing it may cause freed |
| ! * memory to be used: |
| ! * :redir => foo |
| ! * :let foo |
| ! * :redir END |
| */ |
| void |
| ! var_redir_str(value, value_len) |
| char_u *value; |
| ! int value_len; |
| { |
| ! size_t len; |
| |
| if (redir_lval == NULL) |
| return; |
| |
| ! if (value_len == -1) |
| ! len = STRLEN(value); /* Append the entire string */ |
| ! else |
| ! len = value_len; /* Append only "value_len" characters */ |
| |
| ! if (ga_grow(&redir_ga, (int)len) == OK) |
| ! { |
| ! mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len); |
| ! redir_ga.ga_len += len; |
| ! } |
| ! else |
| var_redir_stop(); |
| } |
| |
| /* |
| |
| *** 1018,1025 **** |
| --- 1016,1034 ---- |
| void |
| var_redir_stop() |
| { |
| + typval_T tv; |
| + |
| if (redir_lval != NULL) |
| { |
| + /* Append the trailing NUL. */ |
| + ga_append(&redir_ga, NUL); |
| + |
| + /* Assign the text to the variable. */ |
| + tv.v_type = VAR_STRING; |
| + tv.vval.v_string = redir_ga.ga_data; |
| + set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)"."); |
| + vim_free(tv.vval.v_string); |
| + |
| clear_lval(redir_lval); |
| vim_free(redir_lval); |
| redir_lval = NULL; |
| |
| |
| |
| *** 668,669 **** |
| --- 668,671 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 183, |
| /**/ |
| |
| -- |
| How To Keep A Healthy Level Of Insanity: |
| 16. Have your coworkers address you by your wrestling name, Rock Hard Kim. |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ |
| /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
| \\\ download, build and distribute -- http://www.A-A-P.org /// |
| \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |