Skip to content

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

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
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions