diff --git a/source/blender/blenlib/intern/string_cursor_utf8.c b/source/blender/blenlib/intern/string_cursor_utf8.c index dd3b0a03470..4a9b354ce60 100644 --- a/source/blender/blenlib/intern/string_cursor_utf8.c +++ b/source/blender/blenlib/intern/string_cursor_utf8.c @@ -345,6 +345,7 @@ void BLI_str_cursor_step_bounds_utf8( const char *str, const int str_maxlen, const int pos, int *r_start, int *r_end) { BLI_assert(str_maxlen >= 0); + BLI_assert(pos >= 0 && pos <= str_maxlen); /* Identify the type of characters are on either side of the current cursor position. */ const eStrCursorDelimType prev = (pos > 0) ? cursor_delim_type_utf8(str, str_maxlen, pos - 1) : STRCUR_DELIM_NONE; @@ -373,6 +374,7 @@ void BLI_str_cursor_step_bounds_utf32( const char32_t *str, const int str_maxlen, const int pos, int *r_start, int *r_end) { BLI_assert(str_maxlen >= 0); + BLI_assert(pos >= 0 && pos <= str_maxlen); /* Identify the type of characters are on either side of the current cursor position. */ const eStrCursorDelimType prev = (pos > 0) ? cursor_delim_type_unicode(str[pos - 1]) : STRCUR_DELIM_NONE; diff --git a/source/blender/editors/interface/interface_handlers.cc b/source/blender/editors/interface/interface_handlers.cc index 58bca46f5a1..72b5982da89 100644 --- a/source/blender/editors/interface/interface_handlers.cc +++ b/source/blender/editors/interface/interface_handlers.cc @@ -3771,14 +3771,21 @@ static void ui_do_but_textedit( inbox = ui_searchbox_inside(data->searchbox, event->xy); } - /* for double click: we do a press again for when you first click on button - * (selects all text, no cursor pos) */ + bool is_press_in_button = false; if (ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) { float mx = event->xy[0]; float my = event->xy[1]; ui_window_to_block_fl(data->region, block, &mx, &my); if (ui_but_contains_pt(but, mx, my)) { + is_press_in_button = true; + } + } + + /* for double click: we do a press again for when you first click on button + * (selects all text, no cursor pos) */ + if (ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) { + if (is_press_in_button) { ui_textedit_set_cursor_pos(but, data, event->xy[0]); but->selsta = but->selend = but->pos; data->sel_pos_init = but->pos; @@ -3798,15 +3805,22 @@ static void ui_do_but_textedit( /* only select a word in button if there was no selection before */ if (event->val == KM_DBL_CLICK && had_selection == false) { - int selsta, selend; - BLI_str_cursor_step_bounds_utf8(data->str, strlen(data->str), but->pos, &selsta, &selend); - but->pos = short(selend); - but->selsta = short(selsta); - but->selend = short(selend); - /* Anchor selection to the left side unless the last word. */ - data->sel_pos_init = ((selend == strlen(data->str)) && (selsta != 0)) ? selend : selsta; - retval = WM_UI_HANDLER_BREAK; - changed = true; + if (is_press_in_button) { + const int str_len = strlen(data->str); + /* This may not be necessary, additional check to ensure `pos` is never out of range, + * since negative values aren't acceptable, see: #113154. */ + CLAMP(but->pos, 0, str_len); + + int selsta, selend; + BLI_str_cursor_step_bounds_utf8(data->str, str_len, but->pos, &selsta, &selend); + but->pos = short(selend); + but->selsta = short(selsta); + but->selend = short(selend); + /* Anchor selection to the left side unless the last word. */ + data->sel_pos_init = ((selend == str_len) && (selsta != 0)) ? selend : selsta; + retval = WM_UI_HANDLER_BREAK; + changed = true; + } } else if (inbox) { /* if we allow activation on key press,