mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 22:27:07 +00:00
Fix recorder crash for long state string - enforce at core level (#9696)
* Recorder exception catch for long state string * Revert - Recorder exception catch for long state string * Validate state length at core level * Revert - this reverts commit 9d6bd017d96f20c10204d9bcb71573e3bc005ee3. * Revert - Recorder exception catch for long state string * Fix state TypeError * Test for long state exception
This commit is contained in:
parent
fc8940111d
commit
7987065ad7
@ -32,7 +32,7 @@ from homeassistant.const import (
|
|||||||
EVENT_SERVICE_REMOVED, __version__)
|
EVENT_SERVICE_REMOVED, __version__)
|
||||||
from homeassistant import loader
|
from homeassistant import loader
|
||||||
from homeassistant.exceptions import (
|
from homeassistant.exceptions import (
|
||||||
HomeAssistantError, InvalidEntityFormatError)
|
HomeAssistantError, InvalidEntityFormatError, InvalidStateError)
|
||||||
from homeassistant.util.async import (
|
from homeassistant.util.async import (
|
||||||
run_coroutine_threadsafe, run_callback_threadsafe,
|
run_coroutine_threadsafe, run_callback_threadsafe,
|
||||||
fire_coroutine_threadsafe)
|
fire_coroutine_threadsafe)
|
||||||
@ -65,6 +65,11 @@ def valid_entity_id(entity_id: str) -> bool:
|
|||||||
return ENTITY_ID_PATTERN.match(entity_id) is not None
|
return ENTITY_ID_PATTERN.match(entity_id) is not None
|
||||||
|
|
||||||
|
|
||||||
|
def valid_state(state: str) -> bool:
|
||||||
|
"""Test if an state is valid."""
|
||||||
|
return len(state) < 256
|
||||||
|
|
||||||
|
|
||||||
def callback(func: Callable[..., None]) -> Callable[..., None]:
|
def callback(func: Callable[..., None]) -> Callable[..., None]:
|
||||||
"""Annotation to mark method as safe to call from within the event loop."""
|
"""Annotation to mark method as safe to call from within the event loop."""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
@ -520,13 +525,20 @@ class State(object):
|
|||||||
def __init__(self, entity_id, state, attributes=None, last_changed=None,
|
def __init__(self, entity_id, state, attributes=None, last_changed=None,
|
||||||
last_updated=None):
|
last_updated=None):
|
||||||
"""Initialize a new state."""
|
"""Initialize a new state."""
|
||||||
|
state = str(state)
|
||||||
|
|
||||||
if not valid_entity_id(entity_id):
|
if not valid_entity_id(entity_id):
|
||||||
raise InvalidEntityFormatError((
|
raise InvalidEntityFormatError((
|
||||||
"Invalid entity id encountered: {}. "
|
"Invalid entity id encountered: {}. "
|
||||||
"Format should be <domain>.<object_id>").format(entity_id))
|
"Format should be <domain>.<object_id>").format(entity_id))
|
||||||
|
|
||||||
|
if not valid_state(state):
|
||||||
|
raise InvalidStateError((
|
||||||
|
"Invalid state encountered for entity id: {}. "
|
||||||
|
"State max length is 255 characters.").format(entity_id))
|
||||||
|
|
||||||
self.entity_id = entity_id.lower()
|
self.entity_id = entity_id.lower()
|
||||||
self.state = str(state)
|
self.state = state
|
||||||
self.attributes = MappingProxyType(attributes or {})
|
self.attributes = MappingProxyType(attributes or {})
|
||||||
self.last_updated = last_updated or dt_util.utcnow()
|
self.last_updated = last_updated or dt_util.utcnow()
|
||||||
self.last_changed = last_changed or self.last_updated
|
self.last_changed = last_changed or self.last_updated
|
||||||
|
@ -32,3 +32,9 @@ class PlatformNotReady(HomeAssistantError):
|
|||||||
"""Error to indicate that platform is not ready."""
|
"""Error to indicate that platform is not ready."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidStateError(HomeAssistantError):
|
||||||
|
"""When an invalid state is encountered."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
@ -12,7 +12,8 @@ import pytz
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import homeassistant.core as ha
|
import homeassistant.core as ha
|
||||||
from homeassistant.exceptions import InvalidEntityFormatError
|
from homeassistant.exceptions import (InvalidEntityFormatError,
|
||||||
|
InvalidStateError)
|
||||||
from homeassistant.util.async import run_coroutine_threadsafe
|
from homeassistant.util.async import run_coroutine_threadsafe
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
from homeassistant.util.unit_system import (METRIC_SYSTEM)
|
from homeassistant.util.unit_system import (METRIC_SYSTEM)
|
||||||
@ -421,6 +422,10 @@ class TestState(unittest.TestCase):
|
|||||||
InvalidEntityFormatError, ha.State,
|
InvalidEntityFormatError, ha.State,
|
||||||
'invalid_entity_format', 'test_state')
|
'invalid_entity_format', 'test_state')
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
InvalidStateError, ha.State,
|
||||||
|
'domain.long_state', 't' * 256)
|
||||||
|
|
||||||
def test_domain(self):
|
def test_domain(self):
|
||||||
"""Test domain."""
|
"""Test domain."""
|
||||||
state = ha.State('some_domain.hello', 'world')
|
state = ha.State('some_domain.hello', 'world')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user