Skip to content

EPICS GUI emission: _coerce_pascal_name crashes with IndexError on validated CA ids of all-punctuation #369

@gilesknap

Description

@gilesknap

Follow-up from review of fc8e710 (#358 / PR #360).

The CA id validator (src/fastcs/transports/epics/ca/util.py:16) accepts ids matching [A-Za-z0-9_-]+. So "___" and "-" are valid CA ids.

_coerce_pascal_name in emission.py then routes them through pvi.device.enforce_pascal_case, whose body strips all non-Pascal characters and then unconditionally indexes s[0]:

s = NON_PASCAL_CHARS_RE.sub(lambda _: "", s)
return s[0].upper() + s[1:]

When all characters are stripped, s == "" and s[0].upper() raises IndexError: string index out of rangebefore our guard runs:

candidate = enforce_pascal_case(controller_id)   # raises here
if candidate and not candidate[0].isupper():
    candidate = "X" + candidate
return candidate

Reproduced locally:

>>> enforce_pascal_case('___')
IndexError: string index out of range
>>> enforce_pascal_case('-')
IndexError: string index out of range

So GUI emission blows up at connect() time for a small but legitimate slice of CA-valid ids.

Suggested fix

Pre-strip and check before calling enforce_pascal_case, or fall back to a safe constant:

def _coerce_pascal_name(controller_id: str) -> str:
    stripped = NON_PASCAL_CHARS_RE.sub("", controller_id)
    if not stripped:
        return "X"  # or raise, depending on policy
    candidate = enforce_pascal_case(controller_id)
    if not candidate[0].isupper():
        candidate = "X" + candidate
    return candidate

Refs

  • src/fastcs/transports/epics/emission.py:25-35
  • src/fastcs/transports/epics/ca/util.py:16 (validator regex that lets these ids through)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions