Merge branch 'esp8266-native-shared-helpers' into esp8266-native-build-surgery

This commit is contained in:
J. Nick Koston
2026-08-20 19:51:27 -05:00
2 changed files with 23 additions and 9 deletions
+7 -8
View File
@@ -18,8 +18,8 @@ Caveats
-------
* Only the ``env.Append`` API is captured. ``env.Replace``,
``env.Prepend``, ``env.AddPreAction``, SCons file generators, and any
arbitrary I/O are silently no-ops. Scripts that depend on those will
produce incomplete output.
arbitrary I/O are no-ops, logged once per method. Scripts that depend
on those will produce incomplete output.
* Running arbitrary Python from third-party libraries is a non-trivial
trust decision. The shim does no sandboxing — anything in the
script's process can run. Use only with libraries whose source you
@@ -65,12 +65,11 @@ def apply_extra_script(
library_root = source_path.resolve()
script_path = (source_path / extra_script).resolve()
if not script_path.is_relative_to(library_root):
_LOGGER.warning(
"Ignoring extraScript %s of library %s: it escapes the library directory",
extra_script,
component.name,
# More hostile than a missing script; must not be quieter than it
raise EsphomeError(
f"extraScript {extra_script} of library {component.name} escapes "
"the library directory"
)
return
if not script_path.is_file():
# A declared-but-absent script is a broken or half-downloaded
# package, not an unsupported script; PlatformIO fails on it too
@@ -210,7 +209,7 @@ def run_extra_script(
"__name__": "__pio_extra_script__",
},
)
except Exception as e: # noqa: BLE001 # pylint: disable=broad-exception-caught
except (SystemExit, Exception) as e: # noqa: BLE001 # pylint: disable=broad-exception-caught
# Discard any partial capture: folding half a script's flags into the
# build could produce wrong-output firmware that links cleanly. The
# warning plus the resulting loud link error point back here.
@@ -117,8 +117,10 @@ def test_apply_extra_script_path_traversal_is_rejected(tmp_path):
c.path = library_dir
c.data = {"build": {"extraScript": "../evil.py"}}
apply_extra_script(c, board_mcu=lambda: "esp32", pio_platform="espressif32")
from esphome.core import EsphomeError
with pytest.raises(EsphomeError, match="escapes the library directory"):
apply_extra_script(c, board_mcu=lambda: "esp32", pio_platform="espressif32")
# Nothing was folded into flags: the traversal was rejected before
# the script could run.
assert "flags" not in c.data["build"]
@@ -297,3 +299,16 @@ def test_unsupported_env_method_warns_once(caplog) -> None:
env.Replace(CC="clang")
env.Replace(CC="gcc")
assert caplog.text.count("env.Replace(...) is not supported") == 1
def test_run_extra_script_sys_exit_is_best_effort(tmp_path, caplog) -> None:
"""sys.exit() in a vendored script must not kill the esphome run."""
from esphome.platformio.extra_script import run_extra_script
script = tmp_path / "extra.py"
script.write_text("import sys\nsys.exit(3)\n")
result = run_extra_script(
script, library_dir=tmp_path, board_mcu="esp32", pio_platform="espressif32"
)
assert result.libs == []
assert "ignoring its output" in caplog.text