Mercurial > vim
view src/float.c @ 33664:06b59278bfcf v9.0.2070
patch 9.0.2070: [security] disallow setting env in restricted mode
Commit: https://github.com/vim/vim/commit/6b89dd6a7257a1e2e9c7ea070b407bc4674a5118
Author: Christian Brabandt <cb@256bit.org>
Date: Thu Oct 26 22:14:17 2023 +0200
patch 9.0.2070: [security] disallow setting env in restricted mode
Problem: [security] disallow setting env in restricted mode
Solution: Setting environment variables in restricted mode could
potentially be used to execute shell commands. Disallow this.
restricted mode: disable allow setting of environment variables
Setting environment variables in restricted mode, may have some unwanted
consequences. So, for example by setting $GCONV_PATH in restricted mode
and then calling the iconv() function, one may be able to execute some
unwanted payload, because the `iconv_open()` function internally uses
the `$GCONV_PATH` variable to find its conversion data.
So let's disable setting environment variables, even so this is no
complete protection, since we are not clearing the existing environment.
I tried a few ways but wasn't successful :(
One could also argue to disable the iconv() function completely in
restricted mode, but who knows what other API functions can be
influenced by setting some other unrelated environment variables.
So let's leave it as it is currently.
closes: #13394
See: https://huntr.com/bounties/b0a2eda1-459c-4e36-98e6-0cc7d7faccfe/
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 26 Oct 2023 22:30:03 +0200 |
parents | f1d5ad2b978e |
children |
line wrap: on
line source
/* vi:set ts=8 sts=4 sw=4 noet: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * float.c: Floating point functions */ #define USING_FLOAT_STUFF #include "vim.h" #if defined(FEAT_EVAL) || defined(PROTO) #ifdef VMS # include <float.h> #endif /* * Convert the string "text" to a floating point number. * This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure * this always uses a decimal point. * Returns the length of the text that was consumed. */ int string2float( char_u *text, float_T *value, // result stored here int skip_quotes) { char *s = (char *)text; float_T f; // MS-Windows does not deal with "inf" and "nan" properly. if (STRNICMP(text, "inf", 3) == 0) { *value = INFINITY; return 3; } if (STRNICMP(text, "-inf", 3) == 0) { *value = -INFINITY; return 4; } if (STRNICMP(text, "nan", 3) == 0) { *value = NAN; return 3; } if (skip_quotes && vim_strchr((char_u *)s, '\'') != NULL) { char_u buf[100]; char_u *p; int quotes = 0; vim_strncpy(buf, (char_u *)s, 99); for (p = buf; ; p = skipdigits(p)) { // remove single quotes between digits, not in the exponent if (*p == '\'') { ++quotes; mch_memmove(p, p + 1, STRLEN(p)); } if (!vim_isdigit(*p)) break; } s = (char *)buf; f = strtod(s, &s); *value = f; return (int)((char_u *)s - buf) + quotes; } f = strtod(s, &s); *value = f; return (int)((char_u *)s - text); } /* * Get the float value of "argvars[0]" into "f". * Returns FAIL when the argument is not a Number or Float. */ static int get_float_arg(typval_T *argvars, float_T *f) { if (argvars[0].v_type == VAR_FLOAT) { *f = argvars[0].vval.v_float; return OK; } if (argvars[0].v_type == VAR_NUMBER) { *f = (float_T)argvars[0].vval.v_number; return OK; } emsg(_(e_number_or_float_required)); return FAIL; } /* * "abs(expr)" function */ void f_abs(typval_T *argvars, typval_T *rettv) { if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; if (argvars[0].v_type == VAR_FLOAT) { rettv->v_type = VAR_FLOAT; rettv->vval.v_float = fabs(argvars[0].vval.v_float); } else { varnumber_T n; int error = FALSE; n = tv_get_number_chk(&argvars[0], &error); if (error) rettv->vval.v_number = -1; else if (n > 0) rettv->vval.v_number = n; else rettv->vval.v_number = -n; } } /* * "acos()" function */ void f_acos(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = acos(f); else rettv->vval.v_float = 0.0; } /* * "asin()" function */ void f_asin(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = asin(f); else rettv->vval.v_float = 0.0; } /* * "atan()" function */ void f_atan(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = atan(f); else rettv->vval.v_float = 0.0; } /* * "atan2()" function */ void f_atan2(typval_T *argvars, typval_T *rettv) { float_T fx = 0.0, fy = 0.0; if (in_vim9script() && (check_for_float_or_nr_arg(argvars, 0) == FAIL || check_for_float_or_nr_arg(argvars, 1) == FAIL)) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &fx) == OK && get_float_arg(&argvars[1], &fy) == OK) rettv->vval.v_float = atan2(fx, fy); else rettv->vval.v_float = 0.0; } /* * "ceil({float})" function */ void f_ceil(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = ceil(f); else rettv->vval.v_float = 0.0; } /* * "cos()" function */ void f_cos(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = cos(f); else rettv->vval.v_float = 0.0; } /* * "cosh()" function */ void f_cosh(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = cosh(f); else rettv->vval.v_float = 0.0; } /* * "exp()" function */ void f_exp(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = exp(f); else rettv->vval.v_float = 0.0; } /* * "float2nr({float})" function */ void f_float2nr(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; if (get_float_arg(argvars, &f) != OK) return; if (f <= (float_T)-VARNUM_MAX + DBL_EPSILON) rettv->vval.v_number = -VARNUM_MAX; else if (f >= (float_T)VARNUM_MAX - DBL_EPSILON) rettv->vval.v_number = VARNUM_MAX; else rettv->vval.v_number = (varnumber_T)f; } /* * "floor({float})" function */ void f_floor(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = floor(f); else rettv->vval.v_float = 0.0; } /* * "fmod()" function */ void f_fmod(typval_T *argvars, typval_T *rettv) { float_T fx = 0.0, fy = 0.0; if (in_vim9script() && (check_for_float_or_nr_arg(argvars, 0) == FAIL || check_for_float_or_nr_arg(argvars, 1) == FAIL)) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &fx) == OK && get_float_arg(&argvars[1], &fy) == OK) rettv->vval.v_float = fmod(fx, fy); else rettv->vval.v_float = 0.0; } # if defined(HAVE_MATH_H) || defined(PROTO) /* * "isinf()" function */ void f_isinf(typval_T *argvars, typval_T *rettv) { if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; if (argvars[0].v_type == VAR_FLOAT && isinf(argvars[0].vval.v_float)) rettv->vval.v_number = argvars[0].vval.v_float > 0.0 ? 1 : -1; } /* * "isnan()" function */ void f_isnan(typval_T *argvars, typval_T *rettv) { if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->vval.v_number = argvars[0].v_type == VAR_FLOAT && isnan(argvars[0].vval.v_float); } # endif /* * "log()" function */ void f_log(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = log(f); else rettv->vval.v_float = 0.0; } /* * "log10()" function */ void f_log10(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = log10(f); else rettv->vval.v_float = 0.0; } /* * "pow()" function */ void f_pow(typval_T *argvars, typval_T *rettv) { float_T fx = 0.0, fy = 0.0; if (in_vim9script() && (check_for_float_or_nr_arg(argvars, 0) == FAIL || check_for_float_or_nr_arg(argvars, 1) == FAIL)) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &fx) == OK && get_float_arg(&argvars[1], &fy) == OK) rettv->vval.v_float = pow(fx, fy); else rettv->vval.v_float = 0.0; } /* * round() is not in C90, use ceil() or floor() instead. */ float_T vim_round(float_T f) { return f > 0 ? floor(f + 0.5) : ceil(f - 0.5); } /* * "round({float})" function */ void f_round(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = vim_round(f); else rettv->vval.v_float = 0.0; } /* * "sin()" function */ void f_sin(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = sin(f); else rettv->vval.v_float = 0.0; } /* * "sinh()" function */ void f_sinh(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = sinh(f); else rettv->vval.v_float = 0.0; } /* * "sqrt()" function */ void f_sqrt(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = sqrt(f); else rettv->vval.v_float = 0.0; } /* * "str2float()" function */ void f_str2float(typval_T *argvars, typval_T *rettv) { char_u *p; int isneg; int skip_quotes; if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) return; skip_quotes = argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1]); p = skipwhite(tv_get_string_strict(&argvars[0])); isneg = (*p == '-'); if (*p == '+' || *p == '-') p = skipwhite(p + 1); (void)string2float(p, &rettv->vval.v_float, skip_quotes); if (isneg) rettv->vval.v_float *= -1; rettv->v_type = VAR_FLOAT; } /* * "tan()" function */ void f_tan(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = tan(f); else rettv->vval.v_float = 0.0; } /* * "tanh()" function */ void f_tanh(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) rettv->vval.v_float = tanh(f); else rettv->vval.v_float = 0.0; } /* * "trunc({float})" function */ void f_trunc(typval_T *argvars, typval_T *rettv) { float_T f = 0.0; if (in_vim9script() && check_for_float_or_nr_arg(argvars, 0) == FAIL) return; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) // trunc() is not in C90, use floor() or ceil() instead. rettv->vval.v_float = f > 0 ? floor(f) : ceil(f); else rettv->vval.v_float = 0.0; } #endif