Skip to content

TextInput::secure(true) panics on cursor hit-testing because masked value uses multibyte  #3288

@xMAC94x

Description

@xMAC94x

Is your issue REALLY a bug?

  • My issue is indeed a bug!
  • I am not crazy! I will not fill out this form just to ask a question or request a feature. Pinky promise.

Is there an existing issue for this?

  • I have searched the existing issues.

Is this issue related to iced?

  • My hardware is compatible and my graphics drivers are up-to-date.

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

  1. Create a TextInput with .secure(true).
  2. Enter some text.
  3. Click in the field to reposition the cursor.

Version

  • iced_widget: 0.14.2

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
``

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions