Reject a negative literal symbol, stop on eof in stored blocks, compile the decoder on LibreTiny in CI

This commit is contained in:
J. Nick Koston
2026-09-08 11:20:05 +02:00
parent eefddf85f1
commit 5b5b5e3cc1
7 changed files with 17 additions and 9 deletions
@@ -878,8 +878,9 @@ ota::OTAResponseTypes ESPHomeOTAComponent::inflate_data_(uint8_t *in, size_t ima
session.dest_limit = session.window + OTA_INFLATE_WINDOW_SIZE;
session.flushed = 0;
res = ota_inflate(&session);
if (res < 0) {
// eof means the read callback failed, which is already logged
// A stored block keeps decoding zeros after the read callback failed, so
// eof is checked as well; that failure is already logged
if (res < 0 || session.eof) {
if (!session.eof) {
ESP_LOGW(TAG, "Inflate err %d", res);
}
+3 -3
View File
@@ -124,12 +124,12 @@ class ESPHomeOTAComponent final : public ota::OTAComponent {
// Upload accounting shared by the data loop and the inflate read callback
struct DataTransfer {
size_t ota_size; // bytes the client sends
size_t total{0}; // bytes received so far
size_t ota_size{0}; // bytes the client sends
size_t total{0}; // bytes received so far
#if USE_OTA_VERSION == 2
size_t acknowledged{0};
#endif
uint32_t last_data_ms;
uint32_t last_data_ms{0};
uint32_t last_progress{0};
};
// Receives up to OTA_BUFFER_SIZE bytes of upload data into buf, waiting up to
@@ -334,6 +334,10 @@ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) {
return TINF_DATA_ERROR;
}
if (sym < 0) {
return sym;
}
/* literal byte */
if (sym < 256) {
TINF_PUT(d, sym);
@@ -16,7 +16,8 @@ class ArduinoRP2OTABackend final {
OTAResponseTypes end();
void abort();
// A gzip image is staged on LittleFS as is; the core's OTA stub inflates it
// into the app region at reboot, the same way the ESP8266 bootloader does.
// into the app region at reboot (arduino-pico 2.4.0 and later, RP2350 from
// 4.0.3; ESPHome requires 6.0.0), the same way the ESP8266 bootloader does.
// begin() then sees the gzip size, so only the staging space is checked up
// front; the inflated size is not known until the stub reads the trailer.
static constexpr bool supports_compression() { return true; }
+3 -2
View File
@@ -72,8 +72,9 @@ SERVER_FEATURE_SUPPORTS_PARTITION_ACCESS = 0x02
SERVER_FEATURE_SUPPORTS_NOISE = 0x04
SERVER_FEATURE_SUPPORTS_DEFLATE = 0x08
# Window of the raw deflate stream sent to a device that inflates on the fly;
# the device's OTA_INFLATE_WINDOW_SIZE (4 KB) must be at least 1 << this
# Window of the raw deflate stream sent to a device that inflates on the fly.
# Part of the protocol: the server's deflate bit promises a 4 KB ring window
# (OTA_INFLATE_WINDOW_SIZE), so a larger window needs a new feature bit
DEFLATE_WINDOW_BITS = 12
NOISE_FRAME_INDICATOR = 0x01
@@ -0,0 +1 @@
<<: !include common.yaml
+1 -1
View File
@@ -186,7 +186,7 @@ async def test_host_ota_self_update(
if "OTA staged at" in line:
staged.set()
# The host backend has no gzip support, so the upload negotiates deflate
if " bytes from " in line:
if "Inflated " in line and " bytes from " in line:
inflated.set()
dev.on_log(line)