XKNX / XKNX/xknxtoolkit

[Detail Bug] KNX GUI: Entering/pasting Unicode superscript/subscript digits in Individual Address input crashes the app

Open Beginner friendly
#75 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
4
Forks
0
Avg merge
15h 38m
Merged PRs (30d)
37

Description

Detail Bug Report

https://app.detail.dev/org_62aa40f5-2c23-4914-a665-3bb2068af20e/bugs/bug_62302d4f-6afe-4638-9211-0eb4b8fb1652

Introduced in #26 by @kewde on Sep 6, 2026

Summary

  • Context: render_bounded_numeric_segment in apps/knx-gui/src/knx_gui/widgets/segmented_input.py renders the three dotted Individual Address segments (area / line / device) in the Configure panel - the widget's sole production caller (ConfigurePanel.render, apps/knx-gui/src/knx_gui/plugins/project/ui/configure.py:127-142).
  • Bug: Its callback_edit cleanup filters the live buffer with c.isdigit() and feeds the result straight into int(...). str.isdigit() returns True for Unicode superscripts/subscripts (² U+00B2, ³ U+00B3, ¹ U+00B9, U+2082, …) that int() rejects, so the callback raises ValueError.
  • Actual vs. expected: The widget's docstring (segmented_input.py:30-36) promises "any non-digit character… is corrected live". Typing or pasting ² is promised to be silently cleaned up; instead it throws an unhandled Python ValueError out of the per-frame ImGui callback.
  • Impact: The widget raises mid-frame; imgui.end() and the rest of ConfigurePanel.render are skipped; on the next frame Dear ImGui's Begin() trips IM_ASSERT("Missing End()"); std::terminate is called, the process dies with SIGSEGV (exit code 139). The user loses the entire application from a single keystroke/paste of a superscript "digit".

Code with Bug

    def _filter(data: imgui.InputTextCallbackData) -> int:
        if data.event_flag == imgui.InputTextFlags_.callback_edit:
            text = str(data.buf)[: data.buf_text_len]
            digits = "".join(c for c in text if c.isdigit())[:max_len]   # <-- BUG 🔴 isdigit() admits superscripts/subscripts int() cannot parse
            clamped = str(min(int(digits), max_value)) if digits else ""  # <-- BUG 🔴 raises ValueError for e.g. digits == '²'
            if clamped != text:
                data.delete_chars(0, data.buf_text_len)
                if clamped:
                    data.insert_chars(0, clamped)
            return 0
        # callback_char_filter: only "." needs special handling here - every
        # other non-digit character, excess length and an out-of-range value
        # are all cleaned up by the callback_edit pass above.
        if chr(data.event_char) == ".":
            advance[0] = True
            return 1
        return 0

Explanation

  • callback_char_filter only rejects "."; it accepts all other characters (including ²/) into the input buffer.
  • On the subsequent callback_edit, the buffer is “cleaned” using c.isdigit(). For Unicode superscripts/subscripts, isdigit() is True, so they survive filtering.
  • The filtered string is then passed to int(digits), which does not accept those Unicode numerals, raising ValueError.
  • The exception is unhandled in the production call path (ConfigurePanel.render), so the frame exits without matching imgui.begin()/end(). On the next frame ImGui asserts "Missing End()" and terminates the process.

Recommended Fix

Filter on ASCII decimal digits explicitly:

            digits = "".join(c for c in text if c in "0123456789")[:max_len]

(equivalently c.isascii() and c.isdecimal()).

History

This bug was introduced in commit 1ab42e3b. That commit added the segmented_input.py widget wholesale (PR #26, "segmented Individual Address input, Area/Line/Device bounded"), replacing the old free-form individual-address text field with three bounded numeric segments.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/knx-gui/src/knx_gui/widgets/segmented_input.py, especially render_bounded_numeric_segment and its callback_edit cleanup, then review its sole caller in apps/knx-gui/src/knx_gui/plugins/project/ui/configure.py:127-142. Verify that entering or pasting superscript/subscript digits no longer raises ValueError, leaves the input safely cleaned, or breaks ConfigurePanel.render.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
desktop
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
86/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.