Problem: Cannot make Vim fail on an internal error.
Solution: Add IEMSG() and IEMSG2(). (Domenique Pelle) Avoid reporting an
internal error without mentioning where.
#LEAK_CFLAGS = -DEXITFREE
#LEAK_LIBS = -lccmalloc
+# Uncomment this line to have Vim call abort() when an internal error is
+# detected. Useful when using a tool to find errors.
+#ABORT_CLFAGS = -DABORT_ON_INTERNAL_ERROR
+
#####################################################
### Specific systems, check if yours is listed! ### {{{
#####################################################
PRE_DEFS = -Iproto $(DEFS) $(GUI_DEFS) $(GUI_IPATH) $(CPPFLAGS) $(EXTRA_IPATHS)
POST_DEFS = $(X_CFLAGS) $(MZSCHEME_CFLAGS) $(EXTRA_DEFS)
-ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(PROFILE_CFLAGS) $(SANITIZER_CFLAGS) $(LEAK_CFLAGS) $(POST_DEFS)
+ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(PROFILE_CFLAGS) $(SANITIZER_CFLAGS) $(LEAK_CFLAGS) $(ABORT_CLFAGS) $(POST_DEFS)
# Exclude $CFLAGS for osdef.sh, for Mac 10.4 some flags don't work together
# with "-E".
keylen = (int)STRLEN(key) / 2;
if (keylen == 0)
{
- EMSG(_("E831: bf_key_init() called with empty password"));
+ IEMSG(_("E831: bf_key_init() called with empty password"));
return;
}
for (i = 0; i < keylen; i++)
hi = hash_find(&dict->dv_hashtab, item->di_key);
if (HASHITEM_EMPTY(hi))
- EMSG2(_(e_intern2), "dictitem_remove()");
+ internal_error("dictitem_remove()");
else
hash_remove(&dict->dv_hashtab, hi);
dictitem_free(item);
case CTRL_X_EVAL:
return (c == Ctrl_P || c == Ctrl_N);
}
- EMSG(_(e_internal));
+ internal_error("vim_is_ctrl_x_key()");
return FALSE;
}
}
else
{
- EMSG2(_(e_intern2), "ins_complete()");
+ internal_error("ins_complete()");
return FAIL;
}
{
hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
if (HASHITEM_EMPTY(hi))
- EMSG2(_(e_intern2), "restore_vimvar()");
+ internal_error("restore_vimvar()");
else
hash_remove(&vimvarht, hi);
}
}
else if (*arg != ',' && *arg != ']')
{
- EMSG2(_(e_intern2), "ex_let_vars()");
+ internal_error("ex_let_vars()");
return FAIL;
}
}
}
if (d == NULL)
{
- EMSG2(_(e_intern2), "do_unlet()");
+ internal_error("do_unlet()");
return FAIL;
}
}
case VVAL_NONE: return "v:none";
case VVAL_NULL: return "v:null";
}
- EMSG2(_(e_intern2), "get_var_special_name()");
+ internal_error("get_var_special_name()");
return "42";
}
break;
#endif
case VAR_UNKNOWN:
- EMSG2(_(e_intern2), "get_tv_number(UNKNOWN)");
+ internal_error("get_tv_number(UNKNOWN)");
break;
}
if (denote == NULL) /* useful for values that must be unsigned */
break;
# endif
case VAR_UNKNOWN:
- EMSG2(_(e_intern2), "get_tv_float(UNKNOWN)");
+ internal_error("get_tv_float(UNKNOWN)");
break;
}
return 0;
return;
}
else if (v->di_tv.v_type != tv->v_type)
- EMSG2(_(e_intern2), "set_var()");
+ internal_error("set_var()");
}
clear_tv(&v->di_tv);
}
break;
case VAR_UNKNOWN:
- EMSG2(_(e_intern2), "copy_tv(UNKNOWN)");
+ internal_error("copy_tv(UNKNOWN)");
break;
}
}
ret = FAIL;
break;
case VAR_UNKNOWN:
- EMSG2(_(e_intern2), "item_copy(UNKNOWN)");
+ internal_error("item_copy(UNKNOWN)");
ret = FAIL;
}
--recurse;
break;
#endif
case VAR_UNKNOWN:
- EMSG2(_(e_intern2), "f_empty(UNKNOWN)");
+ internal_error("f_empty(UNKNOWN)");
n = TRUE;
break;
}
case VAR_JOB: n = VAR_TYPE_JOB; break;
case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break;
case VAR_UNKNOWN:
- EMSG2(_(e_intern2), "f_type(UNKNOWN)");
+ internal_error("f_type(UNKNOWN)");
n = -1;
break;
}
if (excp == NULL)
{
- EMSG(_(e_internal));
+ internal_error("discard_exception()");
return;
}
finish_exception(except_T *excp)
{
if (excp != caught_stack)
- EMSG(_(e_internal));
+ internal_error("finish_exception()");
caught_stack = caught_stack->caught;
if (caught_stack != NULL)
{
* ":break", ":return", ":finish", error, interrupt, or another
* exception. */
if (cstack->cs_exception[cstack->cs_idx] != current_exception)
- EMSG(_(e_internal));
+ internal_error("ex_catch()");
}
else
{
* exception will be discarded. */
if (did_throw && cstack->cs_exception[cstack->cs_idx]
!= current_exception)
- EMSG(_(e_internal));
+ internal_error("ex_finally()");
}
/*
}
else if (buf->bh_curr == NULL) /* buffer has already been read */
{
- EMSG(_("E222: Add to read buffer"));
+ IEMSG(_("E222: Add to read buffer"));
return;
}
else if (buf->bh_index != 0)
free_typebuf(void)
{
if (typebuf.tb_buf == typebuf_init)
- EMSG2(_(e_intern2), "Free typebuf 1");
+ internal_error("Free typebuf 1");
else
vim_free(typebuf.tb_buf);
if (typebuf.tb_noremap == noremapbuf_init)
- EMSG2(_(e_intern2), "Free typebuf 2");
+ internal_error("Free typebuf 2");
else
vim_free(typebuf.tb_noremap);
}
c1 = 'l';
break;
default:
- EMSG(_("E228: makemap: Illegal mode"));
+ IEMSG(_("E228: makemap: Illegal mode"));
return FAIL;
}
do /* do this twice if c2 is set, 3 times with c3 */
EXTERN char_u e_fontwidth[] INIT(= N_("E236: Font \"%s\" is not fixed-width"));
#endif
EXTERN char_u e_internal[] INIT(= N_("E473: Internal error"));
+EXTERN char_u e_intern2[] INIT(= N_("E685: Internal error: %s"));
EXTERN char_u e_interr[] INIT(= N_("Interrupted"));
EXTERN char_u e_invaddr[] INIT(= N_("E14: Invalid address"));
EXTERN char_u e_invarg[] INIT(= N_("E474: Invalid argument"));
EXTERN char_u e_guarded[] INIT(= N_("E463: Region is guarded, cannot modify"));
EXTERN char_u e_nbreadonly[] INIT(= N_("E744: NetBeans does not allow changes in read-only files"));
#endif
-EXTERN char_u e_intern2[] INIT(= N_("E685: Internal error: %s"));
EXTERN char_u e_maxmempat[] INIT(= N_("E363: pattern uses more memory than 'maxmempattern'"));
EXTERN char_u e_emptybuf[] INIT(= N_("E749: empty buffer"));
EXTERN char_u e_nobufnr[] INIT(= N_("E86: Buffer %ld does not exist"));
if (mesg != NULL && mesgCB != NULL)
{
- EMSG(_("E232: Cannot create BalloonEval with both message and callback"));
+ IEMSG(_("E232: Cannot create BalloonEval with both message and callback"));
return NULL;
}
if (mesg != NULL && mesgCB != NULL)
{
- EMSG(_("E232: Cannot create BalloonEval with both message and callback"));
+ IEMSG(_("E232: Cannot create BalloonEval with both message and callback"));
return NULL;
}
return AUTOMATA_CORRECT_NEW;
default:
- EMSG(_("E256: Hangul automata ERROR"));
+ IEMSG(_("E256: Hangul automata ERROR"));
break;
}
return AUTOMATA_ERROR; /* RrEeAaLlLlYy EeRrRrOoRr */
hi = hash_lookup(ht, key, hash);
if (!HASHITEM_EMPTY(hi))
{
- EMSG2(_(e_intern2), "hash_add()");
+ internal_error("hash_add()");
return FAIL;
}
return hash_add_item(ht, hi, key, hash);
cs_print_tags_priv(mp, cp, cnt);
break;
default: /* should not reach here */
- (void)EMSG(_("E570: fatal error in cs_manage_matches"));
+ IEMSG(_("E570: fatal error in cs_manage_matches"));
return NULL;
}
break;
#endif
case VAR_UNKNOWN:
- EMSG2(_(e_intern2), "json_encode_item()");
+ internal_error("json_encode_item()");
return FAIL;
}
return OK;
flags = hp->bh_flags;
if ((flags & BH_LOCKED) == 0)
- EMSG(_("E293: block was not locked"));
+ IEMSG(_("E293: block was not locked"));
flags &= ~BH_LOCKED;
if (dirty)
{
goto error;
if (hp->bh_bnum != 0)
{
- EMSG(_("E298: Didn't get block nr 0?"));
+ IEMSG(_("E298: Didn't get block nr 0?"));
goto error;
}
b0p = (ZERO_BL *)(hp->bh_data);
goto error;
if (hp->bh_bnum != 1)
{
- EMSG(_("E298: Didn't get block nr 1?"));
+ IEMSG(_("E298: Didn't get block nr 1?"));
goto error;
}
pp = (PTR_BL *)(hp->bh_data);
goto error;
if (hp->bh_bnum != 2)
{
- EMSG(_("E298: Didn't get block nr 2?"));
+ IEMSG(_("E298: Didn't get block nr 2?"));
goto error;
}
b0p = (ZERO_BL *)(hp->bh_data);
if (ml_check_b0_id(b0p) == FAIL)
- EMSG(_("E304: ml_upd_block0(): Didn't get block 0??"));
+ IEMSG(_("E304: ml_upd_block0(): Didn't get block 0??"));
else
{
if (what == UB_FNAME)
/* Avoid giving this message for a recursive call, may happen when
* the GUI redraws part of the text. */
++recursive;
- EMSGN(_("E315: ml_get: invalid lnum: %ld"), lnum);
+ IEMSGN(_("E315: ml_get: invalid lnum: %ld"), lnum);
--recursive;
}
errorret:
/* Avoid giving this message for a recursive call, may happen
* when the GUI redraws part of the text. */
++recursive;
- EMSGN(_("E316: ml_get: cannot find line %ld"), lnum);
+ IEMSGN(_("E316: ml_get: cannot find line %ld"), lnum);
--recursive;
}
goto errorret;
pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */
if (pp->pb_id != PTR_ID)
{
- EMSG(_("E317: pointer block id wrong 3"));
+ IEMSG(_("E317: pointer block id wrong 3"));
mf_put(mfp, hp, FALSE, FALSE);
return FAIL;
}
*/
if (stack_idx < 0)
{
- EMSG(_("E318: Updated too many blocks?"));
+ IEMSG(_("E318: Updated too many blocks?"));
buf->b_ml.ml_stack_top = 0; /* invalidate stack */
}
}
pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */
if (pp->pb_id != PTR_ID)
{
- EMSG(_("E317: pointer block id wrong 4"));
+ IEMSG(_("E317: pointer block id wrong 4"));
mf_put(mfp, hp, FALSE, FALSE);
return FAIL;
}
hp = ml_find_line(buf, lnum, ML_FIND);
if (hp == NULL)
- EMSGN(_("E320: Cannot find line %ld"), lnum);
+ IEMSGN(_("E320: Cannot find line %ld"), lnum);
else
{
dp = (DATA_BL *)(hp->bh_data);
pp = (PTR_BL *)(dp); /* must be pointer block */
if (pp->pb_id != PTR_ID)
{
- EMSG(_("E317: pointer block id wrong"));
+ IEMSG(_("E317: pointer block id wrong"));
goto error_block;
}
if (idx >= (int)pp->pb_count) /* past the end: something wrong! */
{
if (lnum > buf->b_ml.ml_line_count)
- EMSGN(_("E322: line number out of range: %ld past the end"),
+ IEMSGN(_("E322: line number out of range: %ld past the end"),
lnum - buf->b_ml.ml_line_count);
else
- EMSGN(_("E323: line count wrong in block %ld"), bnum);
+ IEMSGN(_("E323: line count wrong in block %ld"), bnum);
goto error_block;
}
if (action == ML_DELETE)
if (pp->pb_id != PTR_ID)
{
mf_put(mfp, hp, FALSE, FALSE);
- EMSG(_("E317: pointer block id wrong 2"));
+ IEMSG(_("E317: pointer block id wrong 2"));
break;
}
pp->pb_pointer[ip->ip_index].pe_line_count += count;
return msg_attr(s, attr);
}
+
/*
* Print an error message with one "%s" and one string argument.
*/
return emsg3(s, a1, NULL);
}
+/*
+ * Print an error message with one or two "%s" and one or two string arguments.
+ * This is not in message.c to avoid a warning for prototypes.
+ */
+ int
+emsg3(char_u *s, char_u *a1, char_u *a2)
+{
+ if (emsg_not_now())
+ return TRUE; /* no error messages at the moment */
+ vim_snprintf((char *)IObuff, IOSIZE, (char *)s, a1, a2);
+ return emsg(IObuff);
+}
+
+/*
+ * Print an error message with one "%ld" and one long int argument.
+ * This is not in message.c to avoid a warning for prototypes.
+ */
+ int
+emsgn(char_u *s, long n)
+{
+ if (emsg_not_now())
+ return TRUE; /* no error messages at the moment */
+ vim_snprintf((char *)IObuff, IOSIZE, (char *)s, n);
+ return emsg(IObuff);
+}
+
+/*
+ * Same as emsg(...), but abort on error when ABORT_ON_INTERNAL_ERROR is
+ * defined. It is used for internal errors only, so that they can be
+ * detected when fuzzing vim.
+ */
+ void
+iemsg(char_u *s)
+{
+ msg(s);
+#ifdef ABORT_ON_INTERNAL_ERROR
+ abort();
+#endif
+}
+
+
+/*
+ * Same as emsg2(...) but abort on error when ABORT_ON_INTERNAL_ERROR is
+ * defined. It is used for internal errors only, so that they can be
+ * detected when fuzzing vim.
+ */
+ void
+iemsg2(char_u *s, char_u *a1)
+{
+ emsg2(s, a1);
+#ifdef ABORT_ON_INTERNAL_ERROR
+ abort();
+#endif
+}
+
+/*
+ * Same as emsgn(...) but abort on error when ABORT_ON_INTERNAL_ERROR is
+ * defined. It is used for internal errors only, so that they can be
+ * detected when fuzzing vim.
+ */
+ void
+iemsgn(char_u *s, long n)
+{
+ emsgn(s, n);
+#ifdef ABORT_ON_INTERNAL_ERROR
+ abort();
+#endif
+}
+
+/*
+ * Give an "Internal error" message.
+ */
+ void
+internal_error(char *where)
+{
+ IEMSG2(_(e_intern2), where);
+}
+
/* emsg3() and emsgn() are in misc2.c to avoid warnings for the prototypes. */
void
{
/* Don't hide this message */
emsg_silent = 0;
- EMSGN(_("E341: Internal error: lalloc(%ld, )"), size);
+ IEMSGN(_("E341: Internal error: lalloc(%ld, )"), size);
return NULL;
}
p_ea = FALSE;
if (first_tabpage->tp_next != NULL)
do_cmdline_cmd((char_u *)"tabonly!");
- if (firstwin != lastwin)
+ if (!ONE_WINDOW)
do_cmdline_cmd((char_u *)"only!");
# endif
}
#endif
-/*
- * Print an error message with one or two "%s" and one or two string arguments.
- * This is not in message.c to avoid a warning for prototypes.
- */
- int
-emsg3(char_u *s, char_u *a1, char_u *a2)
-{
- if (emsg_not_now())
- return TRUE; /* no error messages at the moment */
- vim_snprintf((char *)IObuff, IOSIZE, (char *)s, a1, a2);
- return emsg(IObuff);
-}
-
-/*
- * Print an error message with one "%ld" and one long int argument.
- * This is not in message.c to avoid a warning for prototypes.
- */
- int
-emsgn(char_u *s, long n)
-{
- if (emsg_not_now())
- return TRUE; /* no error messages at the moment */
- vim_snprintf((char *)IObuff, IOSIZE, (char *)s, n);
- return emsg(IObuff);
-}
-
#if defined(FEAT_SPELL) || defined(FEAT_PERSISTENT_UNDO) || defined(PROTO)
/*
* Read 2 bytes from "fd" and turn them into an int, MSB first.
flagp = insecure_flag(idx, opt_flags);
return (*flagp & P_INSECURE) != 0;
}
- EMSG2(_(e_intern2), "was_set_insecurely()");
+ internal_error("was_set_insecurely()");
return -1;
}
if (idx < 0) /* not found (should not happen) */
{
EMSG2(_(e_intern2), "set_string_option_direct()");
- EMSG2(_("For option %s"), name);
+ IEMSG2(_("For option %s"), name);
return;
}
}
ret = NULL;
break;
default:
- EMSG2(_(e_intern2), "option_iter_next()");
+ internal_error("option_iter_next()");
return NULL;
}
}
#ifdef FEAT_SIGNS
case PV_SCL: return (char_u *)&(curwin->w_p_scl);
#endif
- default: EMSG(_("E356: get_varp ERROR"));
+ default: IEMSG(_("E356: get_varp ERROR"));
}
/* always return a valid pointer to avoid a crash! */
return (char_u *)&(curbuf->b_p_wm);
void do_perror(char *msg);
int emsg(char_u *s);
int emsg2(char_u *s, char_u *a1);
+int emsg3(char_u *s, char_u *a1, char_u *a2);
+int emsgn(char_u *s, long n);
+void iemsg(char_u *s);
+void iemsg2(char_u *s, char_u *a1);
+void iemsgn(char_u *s, long n);
+void internal_error(char *where);
void emsg_invreg(int name);
char_u *msg_trunc_attr(char_u *s, int force, int attr);
char_u *msg_may_trunc(int force, char_u *s);
void sort_strings(char_u **files, int count);
int pathcmp(const char *p, const char *q, int maxlen);
int filewritable(char_u *fname);
-int emsg3(char_u *s, char_u *a1, char_u *a2);
-int emsgn(char_u *s, long n);
int get2c(FILE *fd);
int get3c(FILE *fd);
int get4c(FILE *fd);
{
if (buf != curbuf)
{
- EMSG2(_(e_intern2), "qf_fill_buffer()");
+ internal_error("qf_fill_buffer()");
return;
}
/* Used for an error (down from) vim_regcomp(): give the error message, set
* rc_did_emsg and return NULL */
#define EMSG_RET_NULL(m) return (EMSG(m), rc_did_emsg = TRUE, (void *)NULL)
+#define IEMSG_RET_NULL(m) return (IEMSG(m), rc_did_emsg = TRUE, (void *)NULL)
#define EMSG_RET_FAIL(m) return (EMSG(m), rc_did_emsg = TRUE, FAIL)
#define EMSG2_RET_NULL(m, c) return (EMSG2((m), (c) ? "" : "\\"), rc_did_emsg = TRUE, (void *)NULL)
#define EMSG2_RET_FAIL(m, c) return (EMSG2((m), (c) ? "" : "\\"), rc_did_emsg = TRUE, FAIL)
#define EMSG_ONE_RET_NULL EMSG2_RET_NULL(_("E369: invalid item in %s%%[]"), reg_magic == MAGIC_ALL)
+
#define MAX_LIMIT (32767L << 16L)
static int re_multi_type(int);
case Magic(')'):
if (one_exactly)
EMSG_ONE_RET_NULL;
- EMSG_RET_NULL(_(e_internal)); /* Supposed to be caught earlier. */
+ IEMSG_RET_NULL(_(e_internal)); /* Supposed to be caught earlier. */
/* NOTREACHED */
case Magic('='):
}
else
{
- EMSG(_(e_internal)); /* Shouldn't happen */
+ internal_error("BRACE_LIMITS");
status = RA_FAIL;
}
}
sfwordnr = soundfold_find(slang, goodword);
if (sfwordnr < 0)
{
- EMSG2(_(e_intern2), "add_sound_suggest()");
+ internal_error("add_sound_suggest()");
return;
}
if (uhp == NULL || uhp->uh_walk != mark)
{
/* Need to redo more but can't find it... */
- EMSG2(_(e_intern2), "undo_time()");
+ internal_error("undo_time()");
break;
}
}
#ifdef FEAT_AUTOCMD
unblock_autocmds();
#endif
- EMSG(_("E438: u_undo: line numbers wrong"));
+ IEMSG(_("E438: u_undo: line numbers wrong"));
changed(); /* don't want UNCHANGED now */
return;
}
{
if (curbuf->b_u_newhead == NULL || curbuf->b_u_newhead->uh_entry == NULL)
{
- EMSG(_("E439: undo list corrupt"));
+ IEMSG(_("E439: undo list corrupt"));
return NULL;
}
return curbuf->b_u_newhead->uh_entry;
uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra;
if (uep->ue_bot < 1 || uep->ue_bot > curbuf->b_ml.ml_line_count)
{
- EMSG(_("E440: undo line missing"));
+ IEMSG(_("E440: undo line missing"));
uep->ue_bot = uep->ue_top + 1; /* assume all lines deleted, will
* get all the old lines back
* without deleting the current
#ifdef EXITFREE
if (!entered_free_all_mem)
#endif
- EMSG2(_(e_intern2), "func_unref()");
+ internal_error("func_unref()");
}
if (fp != NULL && --fp->uf_refcount <= 0)
{
else if (isdigit(*name))
/* Only give an error for a numbered function.
* Fail silently, when named or lambda function isn't found. */
- EMSG2(_(e_intern2), "func_ref()");
+ internal_error("func_ref()");
}
/*
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 74,
/**/
73,
/**/
#define EMSG3(s, p, q) emsg3((char_u *)(s), (char_u *)(p), (char_u *)(q))
#define EMSGN(s, n) emsgn((char_u *)(s), (long)(n))
#define EMSGU(s, n) emsgu((char_u *)(s), (long_u)(n))
+#define IEMSG(s) iemsg((char_u *)(s))
+#define IEMSG2(s, p) iemsg2((char_u *)(s), (char_u *)(p))
+#define IEMSGN(s, n) iemsgn((char_u *)(s), (long)(n))
#define OUT_STR(s) out_str((char_u *)(s))
#define OUT_STR_NF(s) out_str_nf((char_u *)(s))
#define MSG_PUTS(s) msg_puts((char_u *)(s))
;
if (ptp == NULL)
{
- EMSG2(_(e_intern2), "win_close_othertab()");
+ internal_error("win_close_othertab()");
return;
}
ptp->tp_next = tp->tp_next;