mirror of
https://github.com/esphome/esphome.git
synced 2026-10-07 03:16:37 +00:00
add max length validation for device class strings
Defense-in-depth: validate device class strings don't exceed the 48-byte PROGMEM buffer limit (47 chars + null), matching the same pattern used for icon strings.
This commit is contained in:
@@ -398,6 +398,10 @@ def string_strict(value):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Max device class string length (47 chars + null = 48-byte PROGMEM buffer)
|
||||||
|
# Keep in sync with MAX_DEVICE_CLASS_LENGTH in esphome/core/entity_base.h
|
||||||
|
DEVICE_CLASS_MAX_LENGTH = 47
|
||||||
|
|
||||||
# Max icon string length (63 chars + null = 64-byte PROGMEM buffer)
|
# Max icon string length (63 chars + null = 64-byte PROGMEM buffer)
|
||||||
# Keep in sync with MAX_ICON_LENGTH in esphome/core/entity_base.h
|
# Keep in sync with MAX_ICON_LENGTH in esphome/core/entity_base.h
|
||||||
ICON_MAX_LENGTH = 63
|
ICON_MAX_LENGTH = 63
|
||||||
|
|||||||
@@ -178,6 +178,10 @@ def _register_string(
|
|||||||
|
|
||||||
def register_device_class(value: str) -> int:
|
def register_device_class(value: str) -> int:
|
||||||
"""Register a device_class string and return its 1-based index."""
|
"""Register a device_class string and return its 1-based index."""
|
||||||
|
if value and len(value) > cv.DEVICE_CLASS_MAX_LENGTH:
|
||||||
|
raise ValueError(
|
||||||
|
f"Device class string too long ({len(value)} chars, max {cv.DEVICE_CLASS_MAX_LENGTH}): '{value}'"
|
||||||
|
)
|
||||||
return _register_string(
|
return _register_string(
|
||||||
value, _get_pool().device_classes, _MAX_DEVICE_CLASSES, "device_class"
|
value, _get_pool().device_classes, _MAX_DEVICE_CLASSES, "device_class"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from esphome.core.entity_helpers import (
|
|||||||
_setup_entity_impl,
|
_setup_entity_impl,
|
||||||
entity_duplicate_validator,
|
entity_duplicate_validator,
|
||||||
get_base_entity_object_id,
|
get_base_entity_object_id,
|
||||||
|
register_device_class,
|
||||||
register_icon,
|
register_icon,
|
||||||
setup_entity,
|
setup_entity,
|
||||||
)
|
)
|
||||||
@@ -926,6 +927,22 @@ def test_register_icon_max_length() -> None:
|
|||||||
assert register_icon("") == 0
|
assert register_icon("") == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_register_device_class_max_length() -> None:
|
||||||
|
"""Test register_device_class rejects device classes exceeding 47 characters."""
|
||||||
|
# 47 chars should succeed
|
||||||
|
max_dc = "a" * 47
|
||||||
|
idx = register_device_class(max_dc)
|
||||||
|
assert idx > 0
|
||||||
|
|
||||||
|
# 48 chars should fail
|
||||||
|
too_long = "a" * 48
|
||||||
|
with pytest.raises(ValueError, match="Device class string too long"):
|
||||||
|
register_device_class(too_long)
|
||||||
|
|
||||||
|
# Empty string returns 0
|
||||||
|
assert register_device_class("") == 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_setup_entity_with_entity_category(
|
async def test_setup_entity_with_entity_category(
|
||||||
setup_test_environment: list[str],
|
setup_test_environment: list[str],
|
||||||
|
|||||||
Reference in New Issue
Block a user