backout https://github.com/vim/vim/commit/bd4614f43d0eac4aff743132bab8e53b015ac801.patch
segfaults seen, at least when using vim-airline

Index: src/eval.c
--- src/eval.c.orig
+++ src/eval.c
@@ -377,12 +377,14 @@ eval_expr_typval(
 {
     if (expr->v_type == VAR_PARTIAL)
 	return eval_expr_partial(expr, argv, argc, fc_arg, rettv);
-    if (expr->v_type == VAR_INSTR)
+    else if (expr->v_type == VAR_INSTR)
 	return exe_typval_instr(expr, rettv);
-    if (expr->v_type == VAR_FUNC || want_func)
+    else if (expr->v_type == VAR_FUNC || want_func)
 	return eval_expr_func(expr, argv, argc, rettv);
+    else
+	return eval_expr_string(expr, rettv);
 
-    return eval_expr_string(expr, rettv);
+    return OK;
 }
 
 /*
@@ -2261,7 +2263,7 @@ set_var_lval(
 
 	    // handle +=, -=, *=, /=, %= and .=
 	    di = NULL;
-	    if (eval_variable(lp->ll_name, (int)(lp->ll_name_end - lp->ll_name),
+	    if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name),
 				 lp->ll_sid, &tv, &di, EVAL_VAR_VERBOSE) == OK)
 	    {
 		if (di != NULL && check_typval_is_value(&di->di_tv) == FAIL)
@@ -6167,34 +6169,19 @@ jobchan_tv2string(
 class_tv2string(typval_T *tv, char_u **tofree)
 {
     char_u	*r = NULL;
-    size_t	rsize;
     class_T	*cl = tv->vval.v_class;
-    char_u	*class_name = (char_u *)"[unknown]";
-    size_t	class_namelen = 9;
     char	*s = "class";
-    size_t	slen = 5;
 
-    if (cl != NULL)
-    {
-	class_name = cl->class_name;
-	class_namelen = STRLEN(cl->class_name);
-	if (IS_INTERFACE(cl))
-	{
-	    s = "interface";
-	    slen = 9;
-	}
-	else if (IS_ENUM(cl))
-	{
-	    s = "enum";
-	    slen = 4;
-	}
-    }
+    if (cl != NULL && IS_INTERFACE(cl))
+	s = "interface";
+    else if (cl != NULL && IS_ENUM(cl))
+	s = "enum";
+    size_t len = STRLEN(s) + 1 +
+				(cl == NULL ? 9 : STRLEN(cl->class_name)) + 1;
+    r = *tofree = alloc(len);
+    vim_snprintf((char *)r, len, "%s %s", s,
+			cl == NULL ? "[unknown]" : (char *)cl->class_name);
 
-    rsize = slen + 1 + class_namelen + 1;
-    r = *tofree = alloc(rsize);
-    if (r != NULL)
-	vim_snprintf((char *)r, rsize, "%s %s", s, (char *)class_name);
-
     return r;
 }
 
@@ -6226,7 +6213,7 @@ object_tv2string(
     else if (copyID != 0 && obj->obj_copyID == copyID
 	    && obj->obj_class->class_obj_member_count != 0)
     {
-	size_t n = 25 + STRLEN((char *)obj->obj_class->class_name);
+	size_t n = 25 + strlen((char *)obj->obj_class->class_name);
 	r = alloc(n);
 	if (r != NULL)
 	    (void)vim_snprintf((char *)r, n, "object of %s {...}",
@@ -6940,14 +6927,14 @@ make_expanded_name(
     temp_result = eval_to_string(expr_start + 1, FALSE, FALSE);
     if (temp_result != NULL)
     {
-	size_t	retvalsize = (size_t)(expr_start - in_start)
-				+ STRLEN(temp_result)
-				+ (size_t)(in_end - expr_end) + 1;
-
-	retval = alloc(retvalsize);
+	retval = alloc(STRLEN(temp_result) + (expr_start - in_start)
+						   + (in_end - expr_end) + 1);
 	if (retval != NULL)
-	    vim_snprintf((char *)retval, retvalsize, "%s%s%s",
-				in_start, temp_result, expr_end + 1);
+	{
+	    STRCPY(retval, in_start);
+	    STRCAT(retval, temp_result);
+	    STRCAT(retval, expr_end + 1);
+	}
     }
     vim_free(temp_result);
 
@@ -7639,17 +7626,21 @@ last_set_msg(sctx_T script_ctx)
     char_u *
 do_string_sub(
     char_u	*str,
-    size_t	len,
     char_u	*pat,
     char_u	*sub,
     typval_T	*expr,
-    char_u	*flags,
-    size_t	*ret_len)		// length of returned buffer
+    char_u	*flags)
 {
+    int		sublen;
     regmatch_T	regmatch;
+    int		i;
+    int		do_all;
+    char_u	*tail;
+    char_u	*end;
     garray_T	ga;
     char_u	*ret;
     char_u	*save_cpo;
+    char_u	*zero_width = NULL;
 
     // Make 'cpoptions' empty, so that the 'l' flag doesn't work here
     save_cpo = p_cpo;
@@ -7657,17 +7648,14 @@ do_string_sub(
 
     ga_init2(&ga, 1, 200);
 
+    do_all = (flags[0] == 'g');
+
     regmatch.rm_ic = p_ic;
     regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
     if (regmatch.regprog != NULL)
     {
-	char_u	*tail = str;
-	char_u	*end = str + len;
-	int	do_all = (flags[0] == 'g');
-	int	sublen;
-	int	i;
-	char_u	*zero_width = NULL;
-
+	tail = str;
+	end = str + STRLEN(str);
 	while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
 	{
 	    // Skip empty match except for first match.
@@ -7722,20 +7710,12 @@ do_string_sub(
 	}
 
 	if (ga.ga_data != NULL)
-	{
 	    STRCPY((char *)ga.ga_data + ga.ga_len, tail);
-	    ga.ga_len += (int)(end - tail);
-	}
 
 	vim_regfree(regmatch.regprog);
     }
 
-    if (ga.ga_data != NULL)
-    {
-	str = (char_u *)ga.ga_data;
-	len = (size_t)ga.ga_len;
-    }
-    ret = vim_strnsave(str, len);
+    ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
     ga_clear(&ga);
     if (p_cpo == empty_option)
 	p_cpo = save_cpo;
@@ -7748,9 +7728,6 @@ do_string_sub(
 	    set_option_value_give_err((char_u *)"cpo", 0L, save_cpo, 0);
 	free_string_option(save_cpo);
     }
-
-    if (ret_len != NULL)
-	*ret_len = len;
 
     return ret;
 }
