XKNX / XKNX/xknxtoolkit

[Detail Bug] Dynamic UI evaluation crashes or mangles labels when TextArg values contain backslashes

Open Beginner friendly
#100 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_c10e9699-c6c2-4247-8073-f338b14be729

Introduced in 09f490434fc1712370be798abbd5984272ff19cd by @kewde on Jun 6, 2026

Summary

  • Context: apply_text_args substitutes {{ArgName}} / {{ArgName:fmt}} placeholders in module name/text templates using the per-instance module text-args before the names of communication objects, parameters, separators, channels, etc. are rendered. These placeholders carry short display labels for module instances (channel numbers, parameter suffixes, com-object names) per the docs (packages/product/docs/knxprod/4-application.mdx).
  • Bug: The text-arg value is passed directly as the repl string to re.sub, so any backslash in a text-arg value is interpreted by CPython's re engine as a replacement escape / backreference instead of a literal character.
  • Actual vs. expected: Actual: backslash sequences in <TextArg Value="..."> (e.g. C:\Users\me, \1, C:\temp) are processed as regex replacement escapes/backrefs during dynamic UI rendering, causing either re.error exceptions or silently altered display strings. Expected: text-arg values should be substituted literally into UI labels.
  • Impact:
    • Crash class: a Value containing \ + an unknown escape letter (e.g. \U, \d) or a backreference (\1, \g<name>) raises re.error from inside DynamicUI.ui(). This blocks every consumer that calls ui() first — encode_to_memory, encode_to_properties, *_param_map, get_module_instances — for the affected Application.
    • Cosmetic class: a Value containing \t / \n / \r is silently mangled in the display label only (e.g. C:\temp renders as C: emp). Encoded parameter/property bytes are not affected.

Code with Bug

packages/product/src/xknxmono/product/parser_v2/_name.py

def apply_text_args(text: str, text_args: dict[str, str]) -> str:
    """Substitute {{ArgName}} and {{ArgName:fmt}} placeholders from module text args."""
    for name, value in text_args.items():
        text = re.sub(r"\{\{" + re.escape(name) + r"(?::[^}]*)?\}\}", value, text)  # <-- BUG 🔴 `value` is a string repl; backslashes become escapes/backrefs and can raise re.error
    return text

Explanation

  • apply_text_args uses re.sub(..., repl=value, ...) where value comes directly from parsed <TextArg Value="..."> (no validation/escaping).
  • In Python re.sub, a string replacement processes backslash escapes and backreferences. Therefore:
    • Values like C:\Users\me trigger re.error: bad escape \U ... during DynamicUI.ui().
    • Values like \1 trigger re.error: invalid group reference 1 ... (the pattern has no capture groups).
    • Values like C:\temp interpret \t as a tab; downstream whitespace normalization collapses it, producing a wrong label.
  • The issue is lazy: loader.load(...) succeeds because apply_text_args is only invoked during dynamic-tree evaluation (app.dynamic_ui().ui() and entrypoints that call ui() first).

Recommended Fix

Use a callable replacement so the value is inserted literally:

for name, value in text_args.items():
    text = re.sub(
        r"\{\{" + re.escape(name) + r"(?::[^}]*)?\}\}",
        lambda _m, v=value: v,
        text,
    )
return text

History

This bug was introduced in commit 09f4904. The change "Render Grid/Table parameter blocks and resolve channel names" rewrote the static substitute_template helper (which substituted {{ArgName}} via safe result.replace(f"{{{{{arg_name}}}}}", arg_value) calls) into a new apply_text_args function that needed to match {{ArgName:fmt}} format-suffix placeholders, so the author switched from str.replace to re.sub and passed the arg value as a string repl — which the re module then interprets for backslash escapes and backreferences, introducing the bug.

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 packages/product/src/xknxmono/product/parser_v2/_name.py at apply_text_args, then trace the app.dynamic_ui().ui() path where text arguments are rendered. Reproduce the issue with values such as C:\temp or \1 and verify that labels retain backslashes literally without raising re.error.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
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.