getdigits: introduce strict, def parameters

Problem:
During a refactor long ago, we changed the `getdigits_*` familiy of
functions to abort on overflow.  But this is often wrong, because many
of these codepaths are handling user input.

Solution:
Decide at each call-site whether to use "strict" mode.

fix #5555
This commit is contained in:
Justin M. Keyes
2019-09-13 18:15:09 -07:00
parent 0a24a2c314
commit 3344cffe7b
22 changed files with 150 additions and 113 deletions

View File

@@ -2071,7 +2071,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
if ((ea.argt & COUNT) && ascii_isdigit(*ea.arg)
&& (!(ea.argt & BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
|| ascii_iswhite(*p))) {
n = getdigits_long(&ea.arg);
n = getdigits_long(&ea.arg, false, -1);
ea.arg = skipwhite(ea.arg);
if (n <= 0 && !ni && (ea.argt & ZEROR) == 0) {
errormsg = (char_u *)_(e_zerocount);
@@ -3797,7 +3797,7 @@ static linenr_T get_address(exarg_T *eap,
default:
if (ascii_isdigit(*cmd)) /* absolute line number */
lnum = getdigits_long(&cmd);
lnum = getdigits_long(&cmd, false, 0);
}
for (;; ) {
@@ -3832,14 +3832,16 @@ static linenr_T get_address(exarg_T *eap,
}
}
if (ascii_isdigit(*cmd))
i = '+'; /* "number" is same as "+number" */
else
if (ascii_isdigit(*cmd)) {
i = '+'; // "number" is same as "+number"
} else {
i = *cmd++;
if (!ascii_isdigit(*cmd)) /* '+' is '+1', but '+0' is not '+1' */
}
if (!ascii_isdigit(*cmd)) { // '+' is '+1', but '+0' is not '+1'
n = 1;
else
n = getdigits(&cmd);
} else {
n = getdigits(&cmd, true, 0);
}
if (addr_type == ADDR_TABS_RELATIVE) {
EMSG(_(e_invrange));
@@ -4504,7 +4506,7 @@ static int get_tabpage_arg(exarg_T *eap)
}
p_save = p;
tab_number = getdigits(&p);
tab_number = getdigits(&p, false, tab_number);
if (relative == 0) {
if (STRCMP(p, "$") == 0) {
@@ -5179,7 +5181,7 @@ two_count:
return FAIL;
}
*def = getdigits_long(&p);
*def = getdigits_long(&p, true, 0);
*argt |= (ZEROR | NOTADR);
if (p != val + vallen || vallen == 0) {
@@ -5196,7 +5198,7 @@ invalid_count:
if (*def >= 0)
goto two_count;
*def = getdigits_long(&p);
*def = getdigits_long(&p, true, 0);
if (p != val + vallen)
goto invalid_count;
@@ -6832,8 +6834,7 @@ static void ex_tabnext(exarg_T *eap)
if (eap->arg && *eap->arg != NUL) {
char_u *p = eap->arg;
char_u *p_save = p;
tab_number = getdigits(&p);
tab_number = getdigits(&p, false, 0);
if (p == p_save || *p_save == '-' || *p_save == '+' || *p != NUL
|| tab_number == 0) {
// No numbers as argument.
@@ -7472,18 +7473,16 @@ static void do_exmap(exarg_T *eap, int isabbrev)
*/
static void ex_winsize(exarg_T *eap)
{
int w, h;
char_u *arg = eap->arg;
char_u *p;
w = getdigits_int(&arg);
char_u *arg = eap->arg;
int w = getdigits_int(&arg, false, 10);
arg = skipwhite(arg);
p = arg;
h = getdigits_int(&arg);
if (*p != NUL && *arg == NUL)
char_u *p = arg;
int h = getdigits_int(&arg, false, 10);
if (*p != NUL && *arg == NUL) {
screen_resize(w, h);
else
} else {
EMSG(_("E465: :winsize requires two number arguments"));
}
}
static void ex_wincmd(exarg_T *eap)
@@ -7745,7 +7744,7 @@ static void ex_later(exarg_T *eap)
if (*p == NUL)
count = 1;
else if (isdigit(*p)) {
count = getdigits_long(&p);
count = getdigits_long(&p, false, 0);
switch (*p) {
case 's': ++p; sec = true; break;
case 'm': ++p; sec = true; count *= 60; break;
@@ -8414,7 +8413,7 @@ static void ex_findpat(exarg_T *eap)
n = 1;
if (ascii_isdigit(*eap->arg)) { /* get count */
n = getdigits_long(&eap->arg);
n = getdigits_long(&eap->arg, false, 0);
eap->arg = skipwhite(eap->arg);
}
if (*eap->arg == '/') { /* Match regexp, not just whole words */
@@ -8660,13 +8659,13 @@ eval_vars (
return NULL;
}
}
/*
* '#': Alternate file name
* '%': Current file name
* File name under the cursor
* File name for autocommand
* and following modifiers
*/
//
// '#': Alternate file name
// '%': Current file name
// File name under the cursor
// File name for autocommand
// and following modifiers
//
else {
switch (spec_idx) {
case SPEC_PERC: /* '%': current file */
@@ -8692,7 +8691,7 @@ eval_vars (
s = src + 1;
if (*s == '<') /* "#<99" uses v:oldfiles */
++s;
i = getdigits_int(&s);
i = getdigits_int(&s, false, 0);
if (s == src + 2 && src[1] == '-') {
// just a minus sign, don't skip over it
s--;