summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2016-10-08 12:46:34 +0200
committerSébastien Helleu <flashcode@flashtux.org>2016-10-08 12:46:34 +0200
commit485aff59c4664ae6e2b39556537616336f66d685 (patch)
treea80b6e1f366c8e909cf60926b7346271789e7d89
parent1635cf50d98283a4a1ff89b86b180083bfcceec1 (diff)
downloadweechat-485aff59c4664ae6e2b39556537616336f66d685.zip
core: fix realloc in function gui_input_optimize_size (issue #809)
This could cause crash in case of memory allocation error (but WeeChat would probably crash or have problems anyway if there's not enough memory for the input line).
-rw-r--r--src/gui/gui-input.c274
-rw-r--r--src/gui/gui-input.h4
2 files changed, 147 insertions, 131 deletions
diff --git a/src/gui/gui-input.c b/src/gui/gui-input.c
index 88c439019..cd5134cf0 100644
--- a/src/gui/gui-input.c
+++ b/src/gui/gui-input.c
@@ -51,34 +51,37 @@ char *gui_input_clipboard = NULL; /* internal clipboard content */
/*
* Optimizes input buffer size by adding or deleting data block (predefined
* size).
+ *
+ * Returns:
+ * 1: input size optimized
+ * 0: error (input and its size are not changed)
*/
-void
-gui_input_optimize_size (struct t_gui_buffer *buffer)
+int
+gui_input_optimize_size (struct t_gui_buffer *buffer,
+ int new_size, int new_length)
{
int optimal_size;
char *input_buffer2;
- if (buffer->input)
+ if (!buffer->input)
+ return 0;
+
+ optimal_size = ((new_size / GUI_BUFFER_INPUT_BLOCK_SIZE) *
+ GUI_BUFFER_INPUT_BLOCK_SIZE) + GUI_BUFFER_INPUT_BLOCK_SIZE;
+ if (buffer->input_buffer_alloc != optimal_size)
{
- optimal_size = ((buffer->input_buffer_size / GUI_BUFFER_INPUT_BLOCK_SIZE) *
- GUI_BUFFER_INPUT_BLOCK_SIZE) + GUI_BUFFER_INPUT_BLOCK_SIZE;
- if (buffer->input_buffer_alloc != optimal_size)
- {
- buffer->input_buffer_alloc = optimal_size;
- input_buffer2 = realloc (buffer->input_buffer, optimal_size);
- if (!input_buffer2)
- {
- if (buffer->input_buffer)
- {
- free (buffer->input_buffer);
- buffer->input_buffer = NULL;
- }
- return;
- }
- buffer->input_buffer = input_buffer2;
- }
+ input_buffer2 = realloc (buffer->input_buffer, optimal_size);
+ if (!input_buffer2)
+ return 0;
+ buffer->input_buffer = input_buffer2;
+ buffer->input_buffer_alloc = optimal_size;
}
+
+ buffer->input_buffer_size = new_size;
+ buffer->input_buffer_length = new_length;
+
+ return 1;
}
/*
@@ -101,16 +104,15 @@ gui_input_replace_input (struct t_gui_buffer *buffer, const char *new_input)
length = utf8_strlen (input_utf8);
/* compute new buffer size */
- buffer->input_buffer_size = size;
- buffer->input_buffer_length = length;
- gui_input_optimize_size (buffer);
-
- /* copy new string to input */
- strcpy (buffer->input_buffer, input_utf8);
+ if (gui_input_optimize_size (buffer, size, length))
+ {
+ /* copy new string to input */
+ strcpy (buffer->input_buffer, input_utf8);
- /* move cursor to the end of new input if it is now after the end */
- if (buffer->input_buffer_pos > buffer->input_buffer_length)
- buffer->input_buffer_pos = buffer->input_buffer_length;
+ /* move cursor to the end of new input if it is now after the end */
+ if (buffer->input_buffer_pos > buffer->input_buffer_length)
+ buffer->input_buffer_pos = buffer->input_buffer_length;
+ }
free (input_utf8);
}
@@ -237,12 +239,9 @@ gui_input_set_pos (struct t_gui_buffer *buffer, int pos)
* Inserts a string into the input buffer.
*
* If pos == -1, string is inserted at cursor position.
- *
- * Returns number of chars inserted (may be different of strlen if UTF-8
- * string).
*/
-int
+void
gui_input_insert_string (struct t_gui_buffer *buffer, const char *string,
int pos)
{
@@ -253,7 +252,7 @@ gui_input_insert_string (struct t_gui_buffer *buffer, const char *string,
{
string_utf8 = strdup (string);
if (!string_utf8)
- return 0;
+ return;
if (pos == -1)
pos = buffer->input_buffer_pos;
@@ -263,27 +262,25 @@ gui_input_insert_string (struct t_gui_buffer *buffer, const char *string,
size = strlen (string_utf8);
length = utf8_strlen (string_utf8);
- /* increase buffer size */
- buffer->input_buffer_size += size;
- buffer->input_buffer_length += length;
- gui_input_optimize_size (buffer);
- buffer->input_buffer[buffer->input_buffer_size] = '\0';
+ if (gui_input_optimize_size (buffer,
+ buffer->input_buffer_size + size,
+ buffer->input_buffer_length + length))
+ {
+ buffer->input_buffer[buffer->input_buffer_size] = '\0';
- /* move end of string to the right */
- ptr_start = (char *)utf8_add_offset (buffer->input_buffer, pos);
- memmove (ptr_start + size, ptr_start, strlen (ptr_start));
+ /* move end of string to the right */
+ ptr_start = (char *)utf8_add_offset (buffer->input_buffer, pos);
+ memmove (ptr_start + size, ptr_start, strlen (ptr_start));
- /* insert new string */
- ptr_start = (char *)utf8_add_offset (buffer->input_buffer, pos);
- strncpy (ptr_start, string_utf8, size);
+ /* insert new string */
+ ptr_start = (char *)utf8_add_offset (buffer->input_buffer, pos);
+ strncpy (ptr_start, string_utf8, size);
- buffer->input_buffer_pos += length;
+ buffer->input_buffer_pos += length;
+ }
free (string_utf8);
-
- return length;
}
- return 0;
}
/*
@@ -422,15 +419,15 @@ gui_input_return (struct t_gui_buffer *buffer)
if (command)
{
gui_history_add (buffer, buffer->input_buffer);
- buffer->input_buffer[0] = '\0';
- buffer->input_buffer_size = 0;
- buffer->input_buffer_length = 0;
- buffer->input_buffer_pos = 0;
- buffer->input_buffer_1st_display = 0;
+ if (gui_input_optimize_size (buffer, 0, 0))
+ {
+ buffer->input_buffer[0] = '\0';
+ buffer->input_buffer_pos = 0;
+ buffer->input_buffer_1st_display = 0;
+ }
gui_buffer_undo_free_all (buffer);
buffer->ptr_history = NULL;
gui_history_ptr = NULL;
- gui_input_optimize_size (buffer);
gui_input_text_changed_modifier_and_signal (buffer,
0, /* save undo */
1); /* stop completion */
@@ -457,18 +454,19 @@ gui_input_complete (struct t_gui_buffer *buffer)
/* replace word with new completed word into input buffer */
if (buffer->completion->diff_size > 0)
{
- buffer->input_buffer_size +=
- buffer->completion->diff_size;
- buffer->input_buffer_length +=
- buffer->completion->diff_length;
- gui_input_optimize_size (buffer);
- buffer->input_buffer[buffer->input_buffer_size] = '\0';
- for (i = buffer->input_buffer_size - 1;
- i >= buffer->completion->position_replace +
- (int)strlen (buffer->completion->word_found); i--)
+ if (gui_input_optimize_size (
+ buffer,
+ buffer->input_buffer_size + buffer->completion->diff_size,
+ buffer->input_buffer_length + buffer->completion->diff_length))
{
- buffer->input_buffer[i] =
- buffer->input_buffer[i - buffer->completion->diff_size];
+ buffer->input_buffer[buffer->input_buffer_size] = '\0';
+ for (i = buffer->input_buffer_size - 1;
+ i >= buffer->completion->position_replace +
+ (int)strlen (buffer->completion->word_found); i--)
+ {
+ buffer->input_buffer[i] =
+ buffer->input_buffer[i - buffer->completion->diff_size];
+ }
}
}
else
@@ -480,10 +478,13 @@ gui_input_complete (struct t_gui_buffer *buffer)
buffer->input_buffer[i] =
buffer->input_buffer[i - buffer->completion->diff_size];
}
- buffer->input_buffer_size += buffer->completion->diff_size;
- buffer->input_buffer_length += buffer->completion->diff_length;
- gui_input_optimize_size (buffer);
- buffer->input_buffer[buffer->input_buffer_size] = '\0';
+ if (gui_input_optimize_size (
+ buffer,
+ buffer->input_buffer_size + buffer->completion->diff_size,
+ buffer->input_buffer_length += buffer->completion->diff_length))
+ {
+ buffer->input_buffer[buffer->input_buffer_size] = '\0';
+ }
}
strncpy (buffer->input_buffer + buffer->completion->position_replace,
@@ -788,11 +789,13 @@ gui_input_delete_previous_char (struct t_gui_buffer *buffer)
char_size = pos - pos_last;
size_to_move = strlen (pos);
memmove (pos_last, pos, size_to_move);
- buffer->input_buffer_size -= char_size;
- buffer->input_buffer_length--;
- buffer->input_buffer_pos--;
- buffer->input_buffer[buffer->input_buffer_size] = '\0';
- gui_input_optimize_size (buffer);
+ if (gui_input_optimize_size (buffer,
+ buffer->input_buffer_size - char_size,
+ buffer->input_buffer_length - 1))
+ {
+ buffer->input_buffer_pos--;
+ buffer->input_buffer[buffer->input_buffer_size] = '\0';
+ }
gui_input_text_changed_modifier_and_signal (buffer,
1, /* save undo */
1); /* stop completion */
@@ -819,10 +822,12 @@ gui_input_delete_next_char (struct t_gui_buffer *buffer)
char_size = pos_next - pos;
size_to_move = strlen (pos_next);
memmove (pos, pos_next, size_to_move);
- buffer->input_buffer_size -= char_size;
- buffer->input_buffer_length--;
- buffer->input_buffer[buffer->input_buffer_size] = '\0';
- gui_input_optimize_size (buffer);
+ if (gui_input_optimize_size (buffer,
+ buffer->input_buffer_size - char_size,
+ buffer->input_buffer_length - 1))
+ {
+ buffer->input_buffer[buffer->input_buffer_size] = '\0';
+ }
gui_input_text_changed_modifier_and_signal (buffer,
1, /* save undo */
1); /* stop completion */
@@ -876,11 +881,14 @@ gui_input_delete_previous_word (struct t_gui_buffer *buffer)
memmove (string, string + size_deleted, strlen (string + size_deleted));
- buffer->input_buffer_size -= size_deleted;
- buffer->input_buffer_length -= length_deleted;
- buffer->input_buffer[buffer->input_buffer_size] = '\0';
- buffer->input_buffer_pos -= length_deleted;
- gui_input_optimize_size (buffer);
+ if (gui_input_optimize_size (
+ buffer,
+ buffer->input_buffer_size - size_deleted,
+ buffer->input_buffer_length - length_deleted))
+ {
+ buffer->input_buffer[buffer->input_buffer_size] = '\0';
+ buffer->input_buffer_pos -= length_deleted;
+ }
gui_input_text_changed_modifier_and_signal (buffer,
1, /* save undo */
1); /* stop completion */
@@ -917,10 +925,13 @@ gui_input_delete_next_word (struct t_gui_buffer *buffer)
memmove (start, string, strlen (string));
- buffer->input_buffer_size -= size_deleted;
- buffer->input_buffer_length -= length_deleted;
- buffer->input_buffer[buffer->input_buffer_size] = '\0';
- gui_input_optimize_size (buffer);
+ if (gui_input_optimize_size (
+ buffer,
+ buffer->input_buffer_size - size_deleted,
+ buffer->input_buffer_length - length_deleted))
+ {
+ buffer->input_buffer[buffer->input_buffer_size] = '\0';
+ }
gui_input_text_changed_modifier_and_signal (buffer,
1, /* save undo */
1); /* stop completion */
@@ -950,11 +961,14 @@ gui_input_delete_beginning_of_line (struct t_gui_buffer *buffer)
memmove (buffer->input_buffer, start, strlen (start));
- buffer->input_buffer_size -= size_deleted;
- buffer->input_buffer_length -= length_deleted;
- buffer->input_buffer[buffer->input_buffer_size] = '\0';
- buffer->input_buffer_pos = 0;
- gui_input_optimize_size (buffer);
+ if (gui_input_optimize_size (
+ buffer,
+ buffer->input_buffer_size - size_deleted,
+ buffer->input_buffer_length - length_deleted))
+ {
+ buffer->input_buffer[buffer->input_buffer_size] = '\0';
+ buffer->input_buffer_pos = 0;
+ }
gui_input_text_changed_modifier_and_signal (buffer,
1, /* save undo */
1); /* stop completion */
@@ -979,9 +993,9 @@ gui_input_delete_end_of_line (struct t_gui_buffer *buffer)
size_deleted = strlen (start);
gui_input_clipboard_copy (start, size_deleted);
start[0] = '\0';
- buffer->input_buffer_size = strlen (buffer->input_buffer);
- buffer->input_buffer_length = utf8_strlen (buffer->input_buffer);
- gui_input_optimize_size (buffer);
+ (void) gui_input_optimize_size (buffer,
+ strlen (buffer->input_buffer),
+ utf8_strlen (buffer->input_buffer));
gui_input_text_changed_modifier_and_signal (buffer,
1, /* save undo */
1); /* stop completion */
@@ -998,11 +1012,11 @@ gui_input_delete_line (struct t_gui_buffer *buffer)
if (buffer->input)
{
gui_buffer_undo_snap (buffer);
- buffer->input_buffer[0] = '\0';
- buffer->input_buffer_size = 0;
- buffer->input_buffer_length = 0;
- buffer->input_buffer_pos = 0;
- gui_input_optimize_size (buffer);
+ if (gui_input_optimize_size (buffer, 0, 0))
+ {
+ buffer->input_buffer[0] = '\0';
+ buffer->input_buffer_pos = 0;
+ }
gui_input_text_changed_modifier_and_signal (buffer,
1, /* save undo */
1); /* stop completion */
@@ -1231,14 +1245,14 @@ gui_input_history_previous (struct t_gui_window *window,
window->buffer->input_buffer);
}
}
- window->buffer->input_buffer_size =
- strlen ((*ptr_history)->text);
- window->buffer->input_buffer_length =
- utf8_strlen ((*ptr_history)->text);
- gui_input_optimize_size (window->buffer);
- window->buffer->input_buffer_pos = window->buffer->input_buffer_length;
- window->buffer->input_buffer_1st_display = 0;
- strcpy (window->buffer->input_buffer, (*ptr_history)->text);
+ if (gui_input_optimize_size (window->buffer,
+ strlen ((*ptr_history)->text),
+ utf8_strlen ((*ptr_history)->text)))
+ {
+ window->buffer->input_buffer_pos = window->buffer->input_buffer_length;
+ window->buffer->input_buffer_1st_display = 0;
+ strcpy (window->buffer->input_buffer, (*ptr_history)->text);
+ }
gui_input_text_changed_modifier_and_signal (window->buffer,
0, /* save undo */
1); /* stop completion */
@@ -1254,12 +1268,13 @@ gui_input_history_next (struct t_gui_window *window,
struct t_gui_history *history,
struct t_gui_history **ptr_history)
{
- int input_changed;
+ int input_changed, rc;
/* make C compiler happy */
(void) history;
input_changed = 0;
+ rc = 0;
if (!window->buffer->input)
return;
@@ -1275,24 +1290,25 @@ gui_input_history_next (struct t_gui_window *window,
*ptr_history = (*ptr_history)->prev_history;
if (*ptr_history)
{
- window->buffer->input_buffer_size =
- strlen ((*ptr_history)->text);
- window->buffer->input_buffer_length =
- utf8_strlen ((*ptr_history)->text);
+ rc = gui_input_optimize_size (window->buffer,
+ strlen ((*ptr_history)->text),
+ utf8_strlen ((*ptr_history)->text));
}
else
{
- window->buffer->input_buffer[0] = '\0';
- window->buffer->input_buffer_size = 0;
- window->buffer->input_buffer_length = 0;
+ rc = gui_input_optimize_size (window->buffer, 0, 0);
+ if (rc)
+ window->buffer->input_buffer[0] = '\0';
}
- gui_input_optimize_size (window->buffer);
- window->buffer->input_buffer_pos =
- window->buffer->input_buffer_length;
- window->buffer->input_buffer_1st_display = 0;
- if (*ptr_history)
+ if (rc)
{
- strcpy (window->buffer->input_buffer, (*ptr_history)->text);
+ window->buffer->input_buffer_pos =
+ window->buffer->input_buffer_length;
+ window->buffer->input_buffer_1st_display = 0;
+ if (*ptr_history)
+ {
+ strcpy (window->buffer->input_buffer, (*ptr_history)->text);
+ }
}
input_changed = 1;
}
@@ -1304,12 +1320,12 @@ gui_input_history_next (struct t_gui_window *window,
window->buffer->input_buffer[window->buffer->input_buffer_size] = '\0';
gui_history_add (window->buffer,
window->buffer->input_buffer);
- window->buffer->input_buffer[0] = '\0';
- window->buffer->input_buffer_size = 0;
- window->buffer->input_buffer_length = 0;
- window->buffer->input_buffer_pos = 0;
- window->buffer->input_buffer_1st_display = 0;
- gui_input_optimize_size (window->buffer);
+ if (gui_input_optimize_size (window->buffer, 0, 0))
+ {
+ window->buffer->input_buffer[0] = '\0';
+ window->buffer->input_buffer_pos = 0;
+ window->buffer->input_buffer_1st_display = 0;
+ }
input_changed = 1;
}
}
diff --git a/src/gui/gui-input.h b/src/gui/gui-input.h
index 415056e28..d7cd1e69e 100644
--- a/src/gui/gui-input.h
+++ b/src/gui/gui-input.h
@@ -35,8 +35,8 @@ extern void gui_input_text_changed_modifier_and_signal (struct t_gui_buffer *buf
int save_undo,
int stop_completion);
extern void gui_input_set_pos (struct t_gui_buffer *buffer, int pos);
-extern int gui_input_insert_string (struct t_gui_buffer *buffer,
- const char *string, int pos);
+extern void gui_input_insert_string (struct t_gui_buffer *buffer,
+ const char *string, int pos);
extern void gui_input_move_to_buffer (struct t_gui_buffer *from_buffer,
struct t_gui_buffer *to_buffer);
extern void gui_input_clipboard_paste (struct t_gui_buffer *buffer);