From aedc3ddd49b50fcee73ad76e193ab0a2c68f4adf Mon Sep 17 00:00:00 2001
From: Benno Schulenberg <bensberg@justemail.net>
Date: Thu, 30 Mar 2017 21:56:31 +0200
Subject: [PATCH] tweaks: replace a function call or a macro with a hard number

Verify at startup that the number is not too small.
---
 src/chars.c  | 43 ++++++++++++++++---------------------------
 src/files.c  |  2 +-
 src/help.c   |  2 +-
 src/nano.c   |  6 +++++-
 src/nano.h   |  7 +++++++
 src/prompt.c |  6 +++---
 src/proto.h  |  1 -
 src/search.c |  4 ++--
 src/text.c   |  8 ++++----
 src/utils.c  |  2 +-
 src/winio.c  |  6 +++---
 11 files changed, 43 insertions(+), 44 deletions(-)

diff --git a/src/chars.c b/src/chars.c
index 0d626ae2..278c73f7 100644
--- a/src/chars.c
+++ b/src/chars.c
@@ -77,7 +77,7 @@ bool is_alpha_mbchar(const char *c)
     if (use_utf8) {
 	wchar_t wc;
 
-	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
+	if (mbtowc(&wc, c, MAXCHARLEN) < 0) {
 	    mbtowc_reset();
 	    return 0;
 	}
@@ -97,7 +97,7 @@ bool is_alnum_mbchar(const char *c)
     if (use_utf8) {
 	wchar_t wc;
 
-	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
+	if (mbtowc(&wc, c, MAXCHARLEN) < 0) {
 	    mbtowc_reset();
 	    return 0;
 	}
@@ -117,7 +117,7 @@ bool is_blank_mbchar(const char *c)
     if (use_utf8) {
 	wchar_t wc;
 
-	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
+	if (mbtowc(&wc, c, MAXCHARLEN) < 0) {
 	    mbtowc_reset();
 	    return 0;
 	}
@@ -165,7 +165,7 @@ bool is_punct_mbchar(const char *c)
     if (use_utf8) {
 	wchar_t wc;
 
-	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
+	if (mbtowc(&wc, c, MAXCHARLEN) < 0) {
 	    mbtowc_reset();
 	    return 0;
 	}
@@ -188,7 +188,7 @@ bool is_word_mbchar(const char *c, bool allow_punct)
 	return TRUE;
 
     if (word_chars != NULL && *word_chars != '\0') {
-	char symbol[mb_cur_max() + 1];
+	char symbol[MAXCHARLEN + 1];
 	int symlen = parse_mbchar(c, symbol, NULL);
 
 	symbol[symlen] = '\0';
@@ -240,7 +240,7 @@ int length_of_char(const char *c, int *width)
 #ifdef ENABLE_UTF8
     if (use_utf8) {
 	wchar_t wc;
-	int charlen = mbtowc(&wc, c, MB_CUR_MAX);
+	int charlen = mbtowc(&wc, c, MAXCHARLEN);
 
 	/* If the sequence is invalid... */
 	if (charlen < 0) {
@@ -273,7 +273,7 @@ int mbwidth(const char *c)
 	wchar_t wc;
 	int width;
 
-	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
+	if (mbtowc(&wc, c, MAXCHARLEN) < 0) {
 	    mbtowc_reset();
 	    return 1;
 	}
@@ -289,17 +289,6 @@ int mbwidth(const char *c)
 	return 1;
 }
 
-/* Return the maximum length (in bytes) of a character. */
-int mb_cur_max(void)
-{
-#ifdef ENABLE_UTF8
-    if (use_utf8)
-	return MB_CUR_MAX;
-    else
-#endif
-	return 1;
-}
-
 /* Convert the Unicode value in chr to a multibyte character, if possible.
  * If the conversion succeeds, return the (dynamically allocated) multibyte
  * character and its length.  Otherwise, return an undefined (dynamically
@@ -310,7 +299,7 @@ char *make_mbchar(long chr, int *chr_mb_len)
 
 #ifdef ENABLE_UTF8
     if (use_utf8) {
-	chr_mb = charalloc(MB_CUR_MAX);
+	chr_mb = charalloc(MAXCHARLEN);
 	*chr_mb_len = wctomb(chr_mb, (wchar_t)chr);
 
 	/* Reject invalid Unicode characters. */
@@ -340,7 +329,7 @@ int parse_mbchar(const char *buf, char *chr, size_t *col)
 #ifdef ENABLE_UTF8
     if (use_utf8) {
 	/* Get the number of bytes in the multibyte character. */
-	length = mblen(buf, MB_CUR_MAX);
+	length = mblen(buf, MAXCHARLEN);
 
 	/* When the multibyte sequence is invalid, only take the first byte. */
 	if (length <= 0) {
@@ -410,10 +399,10 @@ size_t move_mbleft(const char *buf, size_t pos)
     /* There is no library function to move backward one multibyte
      * character.  So we just start groping for one at the farthest
      * possible point. */
-    if (mb_cur_max() > pos)
+    if (pos < MAXCHARLEN)
 	before = 0;
     else
-	before = pos - mb_cur_max();
+	before = pos - MAXCHARLEN;
 
     while (before < pos) {
 	char_len = parse_mbchar(buf + before, NULL, NULL);
@@ -446,12 +435,12 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
 	while (*s1 != '\0' && *s2 != '\0' && n > 0) {
 	    bool bad1 = FALSE, bad2 = FALSE;
 
-	    if (mbtowc(&wc1, s1, MB_CUR_MAX) < 0) {
+	    if (mbtowc(&wc1, s1, MAXCHARLEN) < 0) {
 		mbtowc_reset();
 		bad1 = TRUE;
 	    }
 
-	    if (mbtowc(&wc2, s2, MB_CUR_MAX) < 0) {
+	    if (mbtowc(&wc2, s2, MAXCHARLEN) < 0) {
 		mbtowc_reset();
 		bad2 = TRUE;
 	    }
@@ -625,11 +614,11 @@ char *mbstrchr(const char *s, const char *c)
 #ifdef ENABLE_UTF8
     if (use_utf8) {
 	bool bad_s_mb = FALSE, bad_c_mb = FALSE;
-	char symbol[MB_CUR_MAX];
+	char symbol[MAXCHARLEN];
 	const char *q = s;
 	wchar_t ws, wc;
 
-	if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
+	if (mbtowc(&wc, c, MAXCHARLEN) < 0) {
 	    mbtowc_reset();
 	    wc = (unsigned char)*c;
 	    bad_c_mb = TRUE;
@@ -749,7 +738,7 @@ bool has_blank_mbchars(const char *s)
 {
 #ifdef ENABLE_UTF8
     if (use_utf8) {
-	char symbol[MB_CUR_MAX];
+	char symbol[MAXCHARLEN];
 
 	for (; *s != '\0'; s += move_mbright(s, 0)) {
 	    parse_mbchar(s, symbol, NULL);
diff --git a/src/files.c b/src/files.c
index 32af2da9..6581b2f0 100644
--- a/src/files.c
+++ b/src/files.c
@@ -2633,7 +2633,7 @@ char *input_tab(char *buf, bool allow_files, size_t *place,
 	char *mzero, *glued;
 	const char *lastslash = revstrstr(buf, "/", buf + *place);
 	size_t lastslash_len = (lastslash == NULL) ? 0 : lastslash - buf + 1;
-	char char1[mb_cur_max()], char2[mb_cur_max()];
+	char char1[MAXCHARLEN], char2[MAXCHARLEN];
 	int len1, len2;
 
 	/* Get the number of characters that all matches have in common. */
diff --git a/src/help.c b/src/help.c
index 8a9f7c66..db38701e 100644
--- a/src/help.c
+++ b/src/help.c
@@ -370,7 +370,7 @@ void help_init(void)
      * plus one or two \n's. */
     for (f = allfuncs; f != NULL; f = f->next)
 	if (f->menus & currmenu)
-	    allocsize += (16 * mb_cur_max()) + strlen(f->help) + 2;
+	    allocsize += (16 * MAXCHARLEN) + strlen(f->help) + 2;
 
 #ifndef NANO_TINY
     /* If we're on the main list, we also count the toggle help text.
diff --git a/src/nano.c b/src/nano.c
index abd573ee..514ad51e 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1812,7 +1812,7 @@ int do_mouse(void)
  * TRUE. */
 void do_output(char *output, size_t output_len, bool allow_cntrls)
 {
-    char onechar[mb_cur_max()];
+    char onechar[MAXCHARLEN];
     int char_len;
     size_t current_len = strlen(openfile->current->data);
     size_t i = 0;
@@ -2016,6 +2016,10 @@ int main(int argc, char **argv)
     textdomain(PACKAGE);
 #endif
 
+    if (MB_CUR_MAX > MAXCHARLEN)
+	fprintf(stderr, "Unexpected large character size: %i bytes"
+			" -- please report a bug\n", MB_CUR_MAX);
+
 #if defined(DISABLE_NANORC) && defined(DISABLE_ROOTWRAPPING)
     /* If we don't have rcfile support, --disable-wrapping-as-root is
      * used, and we're root, turn wrapping off. */
diff --git a/src/nano.h b/src/nano.h
index 478fbd8c..f8c4da1e 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -68,6 +68,13 @@
 #define charmove(dest, src, n) memmove(dest, src, (n) * sizeof(char))
 #define charset(dest, src, n) memset(dest, src, (n) * sizeof(char))
 
+/* In UTF-8 a character is at most six bytes long. */
+#ifdef ENABLE_UTF8
+#define MAXCHARLEN 6
+#else
+#define MAXCHARLEN 1
+#endif
+
 /* Set a default value for PATH_MAX if there isn't one. */
 #ifndef PATH_MAX
 #define PATH_MAX 4096
diff --git a/src/prompt.c b/src/prompt.c
index 1d3c4941..13a79497 100644
--- a/src/prompt.c
+++ b/src/prompt.c
@@ -197,7 +197,7 @@ void do_statusbar_output(int *the_input, size_t input_len,
 	bool filtering)
 {
     char *output = charalloc(input_len + 1);
-    char onechar[mb_cur_max()];
+    char onechar[MAXCHARLEN];
     int i, char_len;
 
     /* Copy the typed stuff so it can be treated. */
@@ -631,9 +631,9 @@ int do_prompt(bool allow_tabs, bool allow_files,
 #ifndef NANO_TINY
   redo_theprompt:
 #endif
-    prompt = charalloc((COLS * mb_cur_max()) + 1);
+    prompt = charalloc((COLS * MAXCHARLEN) + 1);
     va_start(ap, msg);
-    vsnprintf(prompt, COLS * mb_cur_max(), msg, ap);
+    vsnprintf(prompt, COLS * MAXCHARLEN, msg, ap);
     va_end(ap);
     /* Reserve five columns for colon plus angles plus answer, ":<aa>". */
     prompt[actual_x(prompt, (COLS < 5) ? 0 : COLS - 5)] = '\0';
diff --git a/src/proto.h b/src/proto.h
index d8255a91..66eefdcf 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -199,7 +199,6 @@ char control_rep(const signed char c);
 char control_mbrep(const char *c, bool isdata);
 int length_of_char(const char *c, int *width);
 int mbwidth(const char *c);
-int mb_cur_max(void);
 char *make_mbchar(long chr, int *chr_mb_len);
 int parse_mbchar(const char *buf, char *chr, size_t *col);
 size_t move_mbleft(const char *buf, size_t pos);
diff --git a/src/search.c b/src/search.c
index 359dbe0d..aa17e673 100644
--- a/src/search.c
+++ b/src/search.c
@@ -1057,12 +1057,12 @@ void do_find_bracket(void)
     wanted_ch_len = parse_mbchar(wanted_ch, NULL, NULL);
 
     /* Fill bracket_set in with the values of ch and wanted_ch. */
-    bracket_set = charalloc((mb_cur_max() * 2) + 1);
+    bracket_set = charalloc((MAXCHARLEN * 2) + 1);
     strncpy(bracket_set, ch, ch_len);
     strncpy(bracket_set + ch_len, wanted_ch, wanted_ch_len);
     bracket_set[ch_len + wanted_ch_len] = '\0';
 
-    found_ch = charalloc(mb_cur_max() + 1);
+    found_ch = charalloc(MAXCHARLEN + 1);
 
     while (TRUE) {
 	if (find_bracket_match(reverse, bracket_set)) {
diff --git a/src/text.c b/src/text.c
index 8579068c..381480ef 100644
--- a/src/text.c
+++ b/src/text.c
@@ -1221,7 +1221,7 @@ void add_undo(undo_type action)
 	    u->xflags = WAS_FINAL_BACKSPACE;
     case DEL:
 	if (openfile->current->data[openfile->current_x] != '\0') {
-	    char *char_buf = charalloc(mb_cur_max() + 1);
+	    char *char_buf = charalloc(MAXCHARLEN + 1);
 	    int char_len = parse_mbchar(&openfile->current->data[u->begin],
 						char_buf, NULL);
 	    char_buf[char_len] = '\0';
@@ -1354,7 +1354,7 @@ fprintf(stderr, "  >> Updating... action = %d, openfile->last_action = %d, openf
 	fprintf(stderr, "  >> openfile->current->data = \"%s\", current_x = %lu, u->begin = %lu\n",
 			openfile->current->data, (unsigned long)openfile->current_x, (unsigned long)u->begin);
 #endif
-	char *char_buf = charalloc(mb_cur_max());
+	char *char_buf = charalloc(MAXCHARLEN);
 	int char_len = parse_mbchar(&openfile->current->data[u->mark_begin_x], char_buf, NULL);
 	u->strdata = addstrings(u->strdata, u->strdata ? strlen(u->strdata) : 0, char_buf, char_len);
 #ifdef DEBUG
@@ -1366,7 +1366,7 @@ fprintf(stderr, "  >> Updating... action = %d, openfile->last_action = %d, openf
     }
     case BACK:
     case DEL: {
-	char *char_buf = charalloc(mb_cur_max());
+	char *char_buf = charalloc(MAXCHARLEN);
 	int char_len = parse_mbchar(&openfile->current->data[openfile->current_x], char_buf, NULL);
 	if (openfile->current_x == u->begin) {
 	    /* They deleted more: add removed character after earlier stuff. */
@@ -1682,7 +1682,7 @@ ssize_t break_line(const char *line, ssize_t goal, bool snap_at_nl)
 size_t indent_length(const char *line)
 {
     size_t len = 0;
-    char onechar[mb_cur_max()];
+    char onechar[MAXCHARLEN];
     int charlen;
 
     while (*line != '\0') {
diff --git a/src/utils.c b/src/utils.c
index 75a5919a..55159e1d 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -215,7 +215,7 @@ const char *fixbounds(const char *r)
  * a separate word?  That is: is it not part of a longer word?*/
 bool is_separate_word(size_t position, size_t length, const char *buf)
 {
-    char before[mb_cur_max()], after[mb_cur_max()];
+    char before[MAXCHARLEN], after[MAXCHARLEN];
     size_t word_end = position + length;
 
     /* Get the characters before and after the word, if any. */
diff --git a/src/winio.c b/src/winio.c
index 7c145368..757ce534 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -1822,7 +1822,7 @@ char *display_string(const char *buf, size_t start_col, size_t span,
     buf += start_index;
 
     /* Allocate enough space for converting the relevant part of the line. */
-    converted = charalloc(strlen(buf) * (mb_cur_max() + tabsize) + 1);
+    converted = charalloc(strlen(buf) * (MAXCHARLEN + tabsize) + 1);
 
     /* If the first character starts before the left edge, or would be
      * overwritten by a "$" token, then show placeholders instead. */
@@ -2136,8 +2136,8 @@ void statusline(message_type importance, const char *msg, ...)
     blank_statusbar();
 
     /* Construct the message out of all the arguments. */
-    compound = charalloc(mb_cur_max() * (COLS + 1));
-    vsnprintf(compound, mb_cur_max() * (COLS + 1), msg, ap);
+    compound = charalloc(MAXCHARLEN * (COLS + 1));
+    vsnprintf(compound, MAXCHARLEN * (COLS + 1), msg, ap);
     va_end(ap);
     message = display_string(compound, 0, COLS, FALSE);
     free(compound);
-- 
GitLab