aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Hinz <mh.codebro@gmail.com>2014-04-23 21:55:12 +0200
committerThiago de Arruda <tpadilha84@gmail.com>2014-04-25 14:09:04 -0300
commit342764d70ee8c9f05f4389a523dfd09f0795fcd1 (patch)
tree3b19485ab56c0da0158d948f8a7724b58feaf0ea
parenta6e1738db31407cdde9cec1e0763f068c7d0a0ae (diff)
downloadrneovim-342764d70ee8c9f05f4389a523dfd09f0795fcd1.tar.gz
rneovim-342764d70ee8c9f05f4389a523dfd09f0795fcd1.tar.bz2
rneovim-342764d70ee8c9f05f4389a523dfd09f0795fcd1.zip
vim-patch:7.4.260
Problem: It is possible to define a function with a colon in the name. It is possible to define a function with a lower case character if a "#" appears after the name. Solution: Disallow using a colon other than with "s:". Ignore "#" after the name. https://code.google.com/p/vim/source/detail?r=6bc874e4789a0f912b4fd6b23afecf19d80b1605
-rw-r--r--src/eval.c71
-rw-r--r--src/testdir/test_eval.in24
-rw-r--r--src/testdir/test_eval.ok2
-rw-r--r--src/version.c2
4 files changed, 70 insertions, 29 deletions
diff --git a/src/eval.c b/src/eval.c
index 54dbd06f79..0fdabdac6c 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -835,7 +835,7 @@ static int eval_fname_sid(char_u *p);
static void list_func_head(ufunc_T *fp, int indent);
static ufunc_T *find_func(char_u *name);
static int function_exists(char_u *name);
-static int builtin_function(char_u *name);
+static bool builtin_function(char_u *name, int len);
static void func_do_profile(ufunc_T *fp);
static void prof_sort_list(FILE *fd, ufunc_T **sorttab, int st_len,
char *title,
@@ -7344,7 +7344,7 @@ call_func (
rettv->vval.v_number = 0;
error = ERROR_UNKNOWN;
- if (!builtin_function(fname)) {
+ if (!builtin_function(fname, -1)) {
/*
* User defined function.
*/
@@ -17353,20 +17353,19 @@ void ex_function(exarg_T *eap)
return;
}
- /*
- * Get the function name. There are these situations:
- * func normal function name
- * "name" == func, "fudi.fd_dict" == NULL
- * dict.func new dictionary entry
- * "name" == NULL, "fudi.fd_dict" set,
- * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
- * dict.func existing dict entry with a Funcref
- * "name" == func, "fudi.fd_dict" set,
- * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
- * dict.func existing dict entry that's not a Funcref
- * "name" == NULL, "fudi.fd_dict" set,
- * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
- */
+ // Get the function name. There are these situations:
+ // func function name
+ // "name" == func, "fudi.fd_dict" == NULL
+ // s:func script-local function name
+ // dict.func new dictionary entry
+ // "name" == NULL, "fudi.fd_dict" set,
+ // "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
+ // dict.func existing dict entry with a Funcref
+ // "name" == func, "fudi.fd_dict" set,
+ // "fudi.fd_di" set, "fudi.fd_newkey" == NULL
+ // dict.func existing dict entry that's not a Funcref
+ // "name" == NULL, "fudi.fd_dict" set,
+ // "fudi.fd_di" set, "fudi.fd_newkey" == NULL
p = eap->arg;
name = trans_function_name(&p, eap->skip, 0, &fudi);
paren = (vim_strchr(p, '(') != NULL);
@@ -17996,12 +17995,22 @@ trans_function_name (
sprintf((char *)sid_buf, "%" PRId64 "_", (int64_t)current_SID);
lead += (int)STRLEN(sid_buf);
}
- } else if (!(flags & TFN_INT) && builtin_function(lv.ll_name)) {
+ } else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, len)) {
EMSG2(_(
- "E128: Function name must start with a capital or contain a colon: %s"),
- lv.ll_name);
+ "E128: Function name must start with a capital or \"s:\": %s"),
+ lv.ll_name);
goto theend;
}
+
+ if (!skip) {
+ char_u *cp = vim_strchr(lv.ll_name, ':');
+
+ if (cp != NULL && cp < end) {
+ EMSG2(_("E884: Function name cannot contain a colon: %s"), lv.ll_name);
+ goto theend;
+ }
+ }
+
name = alloc((unsigned)(len + lead + 1));
if (name != NULL) {
if (lead > 0) {
@@ -18012,7 +18021,7 @@ trans_function_name (
STRCPY(name + 3, sid_buf);
}
memmove(name + lead, lv.ll_name, (size_t)len);
- name[len + lead] = NUL;
+ name[lead + len] = NUL;
}
*pp = end;
@@ -18117,8 +18126,9 @@ void free_all_functions(void)
int translated_function_exists(char_u *name)
{
- if (builtin_function(name))
+ if (builtin_function(name, -1)) {
return find_internal_func(name) >= 0;
+ }
return find_func(name) != NULL;
}
@@ -18158,14 +18168,19 @@ char_u *get_expanded_name(char_u *name, int check)
return NULL;
}
-/*
- * Return TRUE if "name" looks like a builtin function name: starts with a
- * lower case letter and doesn't contain a ':' or AUTOLOAD_CHAR.
- */
-static int builtin_function(char_u *name)
+/// Return TRUE if "name" looks like a builtin function name: starts with a
+/// lower case letter and doesn't contain AUTOLOAD_CHAR.
+/// "len" is the length of "name", or -1 for NUL terminated.
+static bool builtin_function(char_u *name, int len)
{
- return ASCII_ISLOWER(name[0]) && vim_strchr(name, ':') == NULL
- && vim_strchr(name, AUTOLOAD_CHAR) == NULL;
+ if (!ASCII_ISLOWER(name[0])) {
+ return FALSE;
+ }
+
+ char_u *p = vim_strchr(name, AUTOLOAD_CHAR);
+
+ return p == NULL
+ || (len > 0 && p > name + len);
}
/*
diff --git a/src/testdir/test_eval.in b/src/testdir/test_eval.in
new file mode 100644
index 0000000000..44eeabfe73
--- /dev/null
+++ b/src/testdir/test_eval.in
@@ -0,0 +1,24 @@
+STARTTEST
+:" function name includes a colon
+:try
+: func! g:test()
+: echo "test"
+: endfunc
+:catch
+: let @a = v:exception
+:endtry
+:" function name folowed by #
+:try
+: func! test2() "#
+: echo "test2"
+: endfunc
+:catch
+: let @b = v:exception
+:endtry
+:%d
+:pu a
+:pu b
+:1d
+:wq! test.out
+ENDTEST
+start:
diff --git a/src/testdir/test_eval.ok b/src/testdir/test_eval.ok
new file mode 100644
index 0000000000..8aaac316c5
--- /dev/null
+++ b/src/testdir/test_eval.ok
@@ -0,0 +1,2 @@
+Vim(function):E128: Function name must start with a capital or "s:": g:test()
+Vim(function):E128: Function name must start with a capital or "s:": test2() "#
diff --git a/src/version.c b/src/version.c
index b86f2de7a2..f556e932ba 100644
--- a/src/version.c
+++ b/src/version.c
@@ -207,7 +207,7 @@ static int included_patches[] = {
//263,
//262,
261,
- //260,
+ 260,
//259,
//258,
//257,