From 76f4391361f92be3d0cb46b6943931be9821f911 Mon Sep 17 00:00:00 2001 From: Old-Ding <35417409+Old-Ding@users.noreply.github.com> Date: Sat, 11 Jul 2026 11:18:32 +0800 Subject: [PATCH] Reject invalid ExecuteProcess boolean attributes The shell and emulate_tty frontend attributes are static booleans. Prevent XML and YAML parsers from preserving invalid strings, which would otherwise be consumed as truthy values. Signed-off-by: Old-Ding <35417409+Old-Ding@users.noreply.github.com> --- launch/launch/actions/execute_process.py | 6 ++++-- launch_xml/test/launch_xml/test_executable.py | 9 +++++++++ launch_yaml/test/launch_yaml/test_executable.py | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/launch/launch/actions/execute_process.py b/launch/launch/actions/execute_process.py index c74d062d8..cdb401432 100644 --- a/launch/launch/actions/execute_process.py +++ b/launch/launch/actions/execute_process.py @@ -398,12 +398,14 @@ def parse( kwargs['sigterm_timeout'] = str(sigterm_timeout) if 'shell' not in ignore: - shell = entity.get_attr('shell', data_type=bool, optional=True) + shell = entity.get_attr( + 'shell', data_type=bool, optional=True, can_be_str=False) if shell is not None: kwargs['shell'] = shell if 'emulate_tty' not in ignore: - emulate_tty = entity.get_attr('emulate_tty', data_type=bool, optional=True) + emulate_tty = entity.get_attr( + 'emulate_tty', data_type=bool, optional=True, can_be_str=False) if emulate_tty is not None: kwargs['emulate_tty'] = emulate_tty diff --git a/launch_xml/test/launch_xml/test_executable.py b/launch_xml/test/launch_xml/test_executable.py index 647512842..3d507ded0 100644 --- a/launch_xml/test/launch_xml/test_executable.py +++ b/launch_xml/test/launch_xml/test_executable.py @@ -85,5 +85,14 @@ def test_executable_on_exit(): assert isinstance(sub_entities[0], Shutdown) +@pytest.mark.parametrize('attribute', ('shell', 'emulate_tty')) +def test_executable_rejects_invalid_boolean_attributes(attribute): + xml_file = f'' + root_entity, parser = load_no_extensions(io.StringIO(xml_file)) + + with pytest.raises(TypeError, match=f"Attribute '{attribute}'"): + parser.parse_description(root_entity) + + if __name__ == '__main__': test_executable() diff --git a/launch_yaml/test/launch_yaml/test_executable.py b/launch_yaml/test/launch_yaml/test_executable.py index 84bac7183..d1c2ae70f 100644 --- a/launch_yaml/test/launch_yaml/test_executable.py +++ b/launch_yaml/test/launch_yaml/test_executable.py @@ -22,6 +22,8 @@ from parser_no_extensions import load_no_extensions +import pytest + def test_executable(): """Parse executable yaml example.""" @@ -82,5 +84,20 @@ def test_executable_on_exit(): assert isinstance(sub_entities[0], Shutdown) +@pytest.mark.parametrize('attribute', ('shell', 'emulate_tty')) +def test_executable_rejects_invalid_boolean_attributes(attribute): + yaml_file = f"""\ + launch: + - executable: + cmd: echo + {attribute}: invalid + """ + yaml_file = textwrap.dedent(yaml_file) + root_entity, parser = load_no_extensions(io.StringIO(yaml_file)) + + with pytest.raises(TypeError, match=f"Attribute '{attribute}'"): + parser.parse_description(root_entity) + + if __name__ == '__main__': test_executable()