Fix various unsafe string handling in fkeys
Also removes the 2048 input byte limit And fixes utf8 completion chars in some cases
This commit is contained in:
		
							parent
							
								
									99a1fff590
								
							
						
					
					
						commit
						fda692d250
					
				
					 1 changed files with 44 additions and 30 deletions
				
			
		| 
						 | 
				
			
			@ -1409,9 +1409,6 @@ key_action_tab_clean(void)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Used in the followig completers */
 | 
			
		||||
#define COMP_BUF 2048
 | 
			
		||||
 | 
			
		||||
/* For use in sorting the user list for completion */
 | 
			
		||||
static int
 | 
			
		||||
talked_recent_cmp (struct User *a, struct User *b)
 | 
			
		||||
| 
						 | 
				
			
			@ -1425,16 +1422,31 @@ talked_recent_cmp (struct User *a, struct User *b)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define COMP_BUF 2048
 | 
			
		||||
 | 
			
		||||
static inline glong
 | 
			
		||||
len_to_offset (const char *str, glong len)
 | 
			
		||||
{
 | 
			
		||||
	return g_utf8_pointer_to_offset (str, str + len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline glong
 | 
			
		||||
offset_to_len (const char *str, glong offset)
 | 
			
		||||
{
 | 
			
		||||
	return g_utf8_offset_to_pointer (str, offset) - str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 | 
			
		||||
							struct session *sess)
 | 
			
		||||
{
 | 
			
		||||
	int len = 0, elen = 0, i = 0, cursor_pos, ent_start = 0, comp = 0, found = 0,
 | 
			
		||||
	    prefix_len, skip_len = 0, is_nick, is_cmd = 0;
 | 
			
		||||
	char buf[COMP_BUF], ent[CHANLEN], *postfix = NULL, *result, *ch;
 | 
			
		||||
	char ent[CHANLEN], *postfix = NULL, *result, *ch;
 | 
			
		||||
	GList *list = NULL, *tmp_list = NULL;
 | 
			
		||||
	const char *text;
 | 
			
		||||
	GCompletion *gcomp = NULL;
 | 
			
		||||
	GString *buf;
 | 
			
		||||
 | 
			
		||||
	/* force the IM Context to reset */
 | 
			
		||||
	SPELL_ENTRY_SET_EDITABLE (t, FALSE);
 | 
			
		||||
| 
						 | 
				
			
			@ -1448,8 +1460,6 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 | 
			
		|||
 | 
			
		||||
	cursor_pos = SPELL_ENTRY_GET_POS (t);
 | 
			
		||||
 | 
			
		||||
	buf[0] = 0; /* make sure we don't get garbage in the buffer */
 | 
			
		||||
 | 
			
		||||
	/* handle "nick: " or "nick " or "#channel "*/
 | 
			
		||||
	ch = g_utf8_find_prev_char(text, g_utf8_offset_to_pointer(text,cursor_pos));
 | 
			
		||||
	if (ch && ch[0] == ' ')
 | 
			
		||||
| 
						 | 
				
			
			@ -1609,40 +1619,42 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 | 
			
		|||
				/* bash style completion */
 | 
			
		||||
				if (g_list_next(list) != NULL)
 | 
			
		||||
				{
 | 
			
		||||
					buf = g_string_sized_new (MAX(COMP_BUF, len + NICKLEN));
 | 
			
		||||
					if (strlen (result) > elen) /* the largest common prefix is larger than nick, change the data */
 | 
			
		||||
					{
 | 
			
		||||
						if (prefix_len)
 | 
			
		||||
							g_utf8_strncpy (buf, text, prefix_len);
 | 
			
		||||
						strncat (buf, result, COMP_BUF - prefix_len);
 | 
			
		||||
						cursor_pos = strlen (buf);
 | 
			
		||||
							g_string_append_len (buf, text, offset_to_len (text, prefix_len));
 | 
			
		||||
						g_string_append (buf, result);
 | 
			
		||||
						cursor_pos = buf->len;
 | 
			
		||||
						g_free(result);
 | 
			
		||||
						if (postfix)
 | 
			
		||||
						{
 | 
			
		||||
							strcat (buf, " ");
 | 
			
		||||
							strncat (buf, postfix, COMP_BUF - cursor_pos -1);
 | 
			
		||||
							g_string_append_c (buf, ' ');
 | 
			
		||||
							g_string_append (buf, postfix);
 | 
			
		||||
						}
 | 
			
		||||
						SPELL_ENTRY_SET_TEXT (t, buf);
 | 
			
		||||
						SPELL_ENTRY_SET_POS (t, g_utf8_pointer_to_offset(buf, buf + cursor_pos));
 | 
			
		||||
						buf[0] = 0;
 | 
			
		||||
						SPELL_ENTRY_SET_TEXT (t, buf->str);
 | 
			
		||||
						SPELL_ENTRY_SET_POS (t, len_to_offset (buf->str, cursor_pos));
 | 
			
		||||
						g_string_erase (buf, 0, -1);
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
						g_free(result);
 | 
			
		||||
 | 
			
		||||
					while (list)
 | 
			
		||||
					{
 | 
			
		||||
						len = strlen (buf);	/* current buffer */
 | 
			
		||||
						len = buf->len;
 | 
			
		||||
						elen = strlen (list->data);	/* next item to add */
 | 
			
		||||
						if (len + elen + 2 >= COMP_BUF) /* +2 is space + null */
 | 
			
		||||
						{
 | 
			
		||||
							PrintText (sess, buf);
 | 
			
		||||
							buf[0] = 0;
 | 
			
		||||
							len = 0;
 | 
			
		||||
							PrintText (sess, buf->str);
 | 
			
		||||
							g_string_erase (buf, 0, -1);
 | 
			
		||||
						}
 | 
			
		||||
						strcpy (buf + len, (char *) list->data);
 | 
			
		||||
						strcpy (buf + len + elen, " ");
 | 
			
		||||
						g_string_append (buf, (char*)list->data);
 | 
			
		||||
						g_string_append_c (buf, ' ');
 | 
			
		||||
						list = list->next;
 | 
			
		||||
					}
 | 
			
		||||
					PrintText (sess, buf);
 | 
			
		||||
					PrintText (sess, buf->str);
 | 
			
		||||
					g_completion_free(gcomp);
 | 
			
		||||
					g_string_free (buf, TRUE);
 | 
			
		||||
					return 2;
 | 
			
		||||
				}
 | 
			
		||||
				/* Only one matching entry */
 | 
			
		||||
| 
						 | 
				
			
			@ -1654,17 +1666,19 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2,
 | 
			
		|||
	
 | 
			
		||||
	if(result)
 | 
			
		||||
	{
 | 
			
		||||
		buf = g_string_sized_new (len + NICKLEN);
 | 
			
		||||
		if (prefix_len)
 | 
			
		||||
			g_utf8_strncpy(buf, text, prefix_len);
 | 
			
		||||
		strncat (buf, result, COMP_BUF - (prefix_len + 3)); /* make sure nicksuffix and space fits */
 | 
			
		||||
			g_string_append_len (buf, text, offset_to_len (text, prefix_len));
 | 
			
		||||
		g_string_append (buf, result);
 | 
			
		||||
		if(!prefix_len && is_nick)
 | 
			
		||||
			strcat (buf, &prefs.hex_completion_suffix[0]);
 | 
			
		||||
		strcat (buf, " ");
 | 
			
		||||
		cursor_pos = strlen (buf);
 | 
			
		||||
			g_string_append_unichar (buf, g_utf8_get_char_validated ((const char*)&prefs.hex_completion_suffix, -1));
 | 
			
		||||
		g_string_append_c (buf, ' ');
 | 
			
		||||
		cursor_pos = buf->len;
 | 
			
		||||
		if (postfix)
 | 
			
		||||
			strncat (buf, postfix, COMP_BUF - cursor_pos - 2);
 | 
			
		||||
		SPELL_ENTRY_SET_TEXT (t, buf);
 | 
			
		||||
		SPELL_ENTRY_SET_POS (t, g_utf8_pointer_to_offset(buf, buf + cursor_pos));
 | 
			
		||||
			g_string_append (buf, postfix);
 | 
			
		||||
		SPELL_ENTRY_SET_TEXT (t, buf->str);
 | 
			
		||||
		SPELL_ENTRY_SET_POS (t, len_to_offset (buf->str, cursor_pos));
 | 
			
		||||
		g_string_free (buf, TRUE);
 | 
			
		||||
	}
 | 
			
		||||
	if (gcomp)
 | 
			
		||||
		g_completion_free(gcomp);
 | 
			
		||||
| 
						 | 
				
			
			@ -1796,7 +1810,7 @@ replace_handle (GtkWidget *t)
 | 
			
		|||
				snprintf (word, sizeof (word), "%s", pop->cmd);
 | 
			
		||||
			else
 | 
			
		||||
				snprintf (word, sizeof (word), "%s%s", pop->cmd, postfix);
 | 
			
		||||
			strcat (outbuf, word);
 | 
			
		||||
			g_strlcat (outbuf, word, sizeof(outbuf));
 | 
			
		||||
			SPELL_ENTRY_SET_TEXT (t, outbuf);
 | 
			
		||||
			SPELL_ENTRY_SET_POS (t, -1);
 | 
			
		||||
			return;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue