Is your issue REALLY a bug?
Is there an existing issue for this?
Is this issue related to iced?
What happened?
iced_widget 0.14.2 sometimes panics in secure text inputs when the cursor is placed in the password field.
The panic appears to come from mixing a byte offset from hit-testing with a UTF-8 string that contains multibyte mask glyphs.
Panic
thread 'main' panicked at .../iced_widget-0.14.2/src/text_input.rs:1656:19:
byte index 11 is not a char boundary; it is inside '•' (bytes 9..12) of `•••••••••••••`
Relevant code
Value::secure() replaces each grapheme with •:
pub fn secure(&self) -> Self {
Self {
graphemes: std::iter::repeat_n(
String::from("•"),
self.graphemes.len(),
)
.collect(),
}
}
Later, find_cursor_position slices the resulting string using char_offset from hit-testing:
let value = value.to_string();
let char_offset = state
.value
.raw()
.hit_test(Point::new(x + offset, text_bounds.height / 2.0))
.map(text::Hit::cursor)?;
unicode_segmentation::UnicodeSegmentation::graphemes(
&value[..char_offset.min(value.len())],
true,
)
.count()
If char_offset lands in the middle of • (3 bytes in UTF-8), this panics.
Why this seems wrong
hit_test(...).map(text::Hit::cursor) appears to produce an offset suitable for the text buffer/layout, but find_cursor_position then uses it as a byte index into a UTF-8 string. That is only safe if the index is guaranteed to be a char boundary, which is not true for the masked secure value because it uses a multibyte character.
Minimal reproduction
- Create a TextInput with .secure(true).
- Enter some text.
- Click in the field to reposition the cursor.
Version
What is the expected behavior?
Secure text inputs should not panic when clicking or moving the cursor inside the field.
Version
crates.io release
Operating System
Linux
Do you have any log output?
PanicHookInfo: panicked at /home/marcel/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iced_widget-0.14.2/src/text_input.rs:1656:19:
byte index 1 is not a char boundary; it is inside '•' (bytes 0..3) of `••••`
Game version: 779927b1 [2026-03-21]
Backtrace:
0: {closure#0}
at voxygen/src/panic_handler.rs:72:13
1: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
at /rustc/12eb345e5593a10e61b4aef766076c8bd552fea6/library/alloc/src/boxed.rs:1999:9
std::panicking::panic_with_hook
at /rustc/12eb345e5593a10e61b4aef766076c8bd552fea6/library/std/src/panicking.rs:842:13
2: std::panicking::panic_handler::{{closure}}
at /rustc/12eb345e5593a10e61b4aef766076c8bd552fea6/library/std/src/panicking.rs:707:13
3: std::sys::backtrace::__rust_end_short_backtrace
at /rustc/12eb345e5593a10e61b4aef766076c8bd552fea6/library/std/src/sys/backtrace.rs:174:18
4: __rustc::rust_begin_unwind
at /rustc/12eb345e5593a10e61b4aef766076c8bd552fea6/library/std/src/panicking.rs:698:5
5: core::panicking::panic_fmt
at /rustc/12eb345e5593a10e61b4aef766076c8bd552fea6/library/core/src/panicking.rs:75:14
6: core::str::slice_error_fail_rt
7: core::str::slice_error_fail
at /rustc/12eb345e5593a10e61b4aef766076c8bd552fea6/library/core/src/str/mod.rs:69:5
8: index
at /home/marcel/m2/.rustup/toolchains/nightly-2025-09-08-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/str/traits.rs:478:21
index<core::ops::range::RangeTo<usize>>
at /home/marcel/m2/.rustup/toolchains/nightly-2025-09-08-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/string.rs:2707:15
find_cursor_position<veloren_voxygen::ui::ice::renderer::widget::text::Paragraph>
at /home/marcel/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iced_widget-0.14.2/src/text_input.rs:1656:19
9: update<veloren_voxygen::menu::main::ui::Message, veloren_voxygen::ui::ice::renderer::style::Theme, veloren_voxygen::ui::ice::renderer::IcedRenderer>
at /home/marcel/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iced_widget-0.14.2/src/text_input.rs:767:33
10: update<veloren_voxygen::menu::main::ui::Message, veloren_voxygen::ui::ice::renderer::IcedRenderer, veloren_voxygen::ui::ice::widget::image::Image>
at voxygen/src/ui/ice/widget/background_container.rs:334:38
11: update<veloren_voxygen::menu::char_selection::ui::Message, veloren_voxygen::ui::ice::renderer::style::Theme, veloren_voxygen::ui::ice::renderer::IcedRenderer>
at /home/marcel/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iced_widget-0.14.2/src/column.rs:278:35
12: update<veloren_voxygen::menu::char_selection::ui::Message, veloren_voxygen::ui::ice::renderer::style::Theme, veloren_voxygen::ui::ice::renderer::IcedRenderer>
at /home/marcel/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iced_widget-0.14.2/src/column.rs:278:35
13: update<veloren_voxygen::menu::main::ui::Message, veloren_voxygen::ui::ice::renderer::IcedRenderer>
at voxygen/src/ui/ice/widget/container.rs:178:38
14: update<veloren_voxygen::menu::main::ui::Message, veloren_voxygen::ui::ice::renderer::IcedRenderer>
at voxygen/src/ui/ice/widget/container.rs:178:38
15: update<veloren_voxygen::menu::server_info::Message, veloren_voxygen::ui::ice::renderer::style::Theme, veloren_voxygen::ui::ice::renderer::IcedRenderer>
at /home/marcel/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iced_widget-0.14.2/src/row.rs:267:35
16: update<veloren_voxygen::menu::char_selection::ui::Message, veloren_voxygen::ui::ice::renderer::style::Theme, veloren_voxygen::ui::ice::renderer::IcedRenderer>
at /home/marcel/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iced_widget-0.14.2/src/column.rs:278:35
17: update<veloren_voxygen::menu::main::ui::Message, veloren_voxygen::ui::ice::renderer::IcedRenderer>
at voxygen/src/ui/ice/widget/container.rs:178:38
``
Is your issue REALLY a bug?
Is there an existing issue for this?
Is this issue related to iced?
What happened?
iced_widget0.14.2sometimes panics in secure text inputs when the cursor is placed in the password field.The panic appears to come from mixing a byte offset from hit-testing with a UTF-8 string that contains multibyte mask glyphs.
Panic
Relevant code
Value::secure() replaces each grapheme with •:
Later, find_cursor_position slices the resulting string using char_offset from hit-testing:
If char_offset lands in the middle of • (3 bytes in UTF-8), this panics.
Why this seems wrong
hit_test(...).map(text::Hit::cursor)appears to produce an offset suitable for the text buffer/layout, but find_cursor_position then uses it as a byte index into a UTF-8 string. That is only safe if the index is guaranteed to be a char boundary, which is not true for the masked secure value because it uses a multibyte character.Minimal reproduction
Version
What is the expected behavior?
Secure text inputs should not panic when clicking or moving the cursor inside the field.
Version
crates.io release
Operating System
Linux
Do you have any log output?