From 45a72fa2168b37c5b213520a44e60b8b97002b52 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 15 Jun 2026 23:05:04 +0200 Subject: [PATCH] Berry multiple minor fixes (#24842) --- .../tasmota_xdrv_driver/xdrv_52_3_berry_flash.ino | 6 +++--- tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino | 7 +++++++ .../tasmota_xdrv_driver/xdrv_52_3_berry_light.ino | 1 - tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mdns.ino | 2 +- .../tasmota_xdrv_driver/xdrv_52_3_berry_onewire.ino | 2 +- .../tasmota_xdrv_driver/xdrv_52_3_berry_pixmat.ino | 8 ++++---- .../xdrv_52_3_berry_tcpclientasync.ino | 4 ++-- .../xdrv_52_3_berry_tcpserver.ino | 12 ++++++++---- .../tasmota_xdrv_driver/xdrv_52_3_berry_webcam.ino | 3 ++- .../xdrv_52_3_berry_webclient.ino | 4 ++-- .../tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino | 2 +- 11 files changed, 31 insertions(+), 20 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_flash.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_flash.ino index afc0ff0c2..c807bf466 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_flash.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_flash.ino @@ -1,5 +1,5 @@ /* - xdrv_52_3_berry_webserver.ino - Berry scripting language, webserver module + xdrv_52_3_berry_flash.ino - Berry scripting language, flash and OTA partition module Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry @@ -65,9 +65,9 @@ size_t FlashWriteSubSector(uint32_t address_start, const uint8_t *data, size_t s #endif if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not erase flash sector 0x%X ret=%i", page_addr / SPI_FLASH_SEC_SIZE, ret); return 0; } #if ESP_IDF_VERSION_MAJOR < 5 - spi_flash_write(page_addr, buffer, SPI_FLASH_SEC_SIZE); + ret = spi_flash_write(page_addr, buffer, SPI_FLASH_SEC_SIZE); #else - esp_flash_write(NULL, buffer, page_addr, SPI_FLASH_SEC_SIZE); + ret = esp_flash_write(NULL, buffer, page_addr, SPI_FLASH_SEC_SIZE); #endif if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not write flash %p (0x%X) ret=%i", page_addr, SPI_FLASH_SEC_SIZE, ret); return 0; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino index 08f9b9527..f7a616b44 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino @@ -343,6 +343,13 @@ extern "C" { uint8_t * pixels = (uint8_t*) be_tocomptr(vm, 2); // arg3: pixels_count:int int32_t pixels_count = be_toint(vm, 3); + // sanity check: each pixel reads one uint32_t (4 bytes 0xAARRGGBB) from `buffer`. + // Guard against a negative count (would wrap in the unsigned loop below) and clamp + // to the source buffer size to avoid out-of-bounds reads. + if (pixels_count < 0) { pixels_count = 0; } + if ((size_t)pixels_count * 4 > buffer_length) { + pixels_count = buffer_length / 4; + } // arg4: pixel_size:int size_t pixel_size = 3; // 0xRRGGBB if (top >= 4 && be_isint(vm, 4)) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_light.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_light.ino index da75b5511..969c331f0 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_light.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_light.ino @@ -208,7 +208,6 @@ extern "C" { int32_t list_size = get_list_size(vm); // AddLog(LOG_LEVEL_INFO, "Instance is list size = %d", list_size); - uint8_t channels[LST_MAX] = {}; // initialized with all zeroes if (list_size > LST_MAX) { list_size = LST_MAX; } // no more than 5 channels, no need to test for positive, any negative will be discarded by loop for (uint32_t i = 0; i < list_size; i++) { // be_dumpstack(vm); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mdns.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mdns.ino index ca45f5ccc..8a25b8a5e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mdns.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mdns.ino @@ -218,7 +218,7 @@ extern "C" { const char* hostname = be_tostring(vm, 1); const char* ip_text = nullptr; for (uint16_t i = 2; i <= top; i++) { - const char* ip_text = be_tostring(vm, i); + ip_text = be_tostring(vm, i); if (ip_text == nullptr || ip_text[0] == 0) { continue; } // ignore empty string IPAddress ip; if (!ip.fromString(ip_text)) { err = -1; break; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_onewire.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_onewire.ino index a173b4b8e..cdd4df7ae 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_onewire.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_onewire.ino @@ -1,5 +1,5 @@ /* - xdrv_52_3_berry_native.ino - Berry scripting language, native fucnctions + xdrv_52_3_berry_onewire.ino - Berry scripting language, OneWire class Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_pixmat.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_pixmat.ino index df19d29a2..42cffb0f0 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_pixmat.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_pixmat.ino @@ -167,8 +167,8 @@ int be_pixmat_init(bvm* vm) { mc->serpentine = (argc >= 6) ? be_tobool(vm, 6) : false; mc->external = true; - if (mc->width <= 0 || mc->height <= 0 || mc->bpp <= 0) { - delete mc; be_raise(vm, "value_error", "invalid dimensions or bpp"); + if (mc->width <= 0 || mc->height <= 0 || mc->bpp <= 0 || mc->bpp > 8) { + delete mc; be_raise(vm, "value_error", "invalid dimensions or bpp (max bpp is 8)"); } size_t need = (size_t)mc->width * (size_t)mc->height; if (mc->bpp > 0 && need > (std::numeric_limits::max)() / (size_t)mc->bpp) { @@ -188,8 +188,8 @@ int be_pixmat_init(bvm* vm) { mc->serpentine = (argc >= 5) ? be_tobool(vm, 5) : false; mc->external = false; - if (mc->width <= 0 || mc->height <= 0 || mc->bpp <= 0) { - delete mc; be_raise(vm, "value_error", "invalid dimensions or bpp"); + if (mc->width <= 0 || mc->height <= 0 || mc->bpp <= 0 || mc->bpp > 8) { + delete mc; be_raise(vm, "value_error", "invalid dimensions or bpp (max bpp is 8)"); } size_t need = (size_t)mc->width * (size_t)mc->height; if (mc->bpp > 0 && need > (std::numeric_limits::max)() / (size_t)mc->bpp) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino index 3ae1c4943..0fcdea09c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino @@ -64,7 +64,7 @@ public: } void stop() { - if (sockfd > 0) { + if (sockfd >= 0) { close(sockfd); } sockfd = -1; @@ -347,7 +347,7 @@ public: void update_local_addr_port(void) { local_port = -1; // default to unknwon - if (sockfd > 0) { + if (sockfd >= 0) { struct sockaddr_storage local_address; socklen_t addr_size = sizeof(local_address); // getpeername(fd, (struct sockaddr*)&addr, &len); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino index 7d2a5d966..78c7523b9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino @@ -140,15 +140,19 @@ void WiFiServerAsync::begin(uint16_t port, int enable){ if (sockfd < 0) return; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); + memset(&server, 0, sizeof(server)); // zero-init, also sets address to in6addr_any (bind to all interfaces) server.sin6_family = AF_INET6; if (_addr.type() == IPv4) { - memcpy(server.sin6_addr.s6_addr+11, (uint8_t*)&_addr[0], 4); - server.sin6_addr.s6_addr[10] = 0xFF; - server.sin6_addr.s6_addr[11] = 0xFF; + // bind to a specific IPv4 address using an IPv4-mapped IPv6 address `::ffff:a.b.c.d` + // a wildcard IPv4 (0.0.0.0) is left as in6addr_any so we keep listening on all interfaces (dual-stack) + if ((uint32_t)_addr != 0) { + server.sin6_addr.s6_addr[10] = 0xFF; + server.sin6_addr.s6_addr[11] = 0xFF; + memcpy(server.sin6_addr.s6_addr + 12, (uint8_t*)&_addr[0], 4); + } } else { memcpy(server.sin6_addr.s6_addr, (uint8_t*)&_addr[0], 16); } - memset(server.sin6_addr.s6_addr, 0x0, 16); server.sin6_port = htons(_port); if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { lwip_close(sockfd); // close fd to avoid leak on bind failure diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webcam.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webcam.ino index 499de2c56..58e9d7871 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webcam.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webcam.ino @@ -111,8 +111,8 @@ extern "C" { if (argc >= 1 && be_isinstance(vm, 1)) { const char * c = be_classname(vm, 1); if(strcmp(c,"img") != 0) { + esp_camera_fb_return(wc_fb); // release frame buffer before raising (be_raise does not return) be_raise(vm, "cam_error", "instance not of img class"); - esp_camera_fb_return(wc_fb); be_return_nil(vm); } image_t * img = be_get_image_instance(vm); @@ -131,6 +131,7 @@ extern "C" { img->buf = (uint8_t*)heap_caps_realloc((void*)img->buf, wc_fb->width * wc_fb->height * bpp, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if(!img->buf){ be_img_util::clear(img); + esp_camera_fb_return(wc_fb); // release frame buffer before raising (be_raise does not return) be_raise(vm, "cam_error", "reallocation failed"); be_return_nil(vm); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino index 9723f7dc8..7693b4115 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino @@ -1,5 +1,5 @@ /* - * xdrv_52_3_berry_webserver.ino — Berry scripting language, webserver/webclient module + * xdrv_52_3_berry_webclient.ino — Berry scripting language, webclient/TCP client module * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -423,7 +423,7 @@ extern "C" { int32_t wc_addheader(struct bvm *vm); int32_t wc_addheader(struct bvm *vm) { int32_t argc = be_top(vm); - if (argc >= 3 && (be_isstring(vm, 2) || be_isstring(vm, 2))) { + if (argc >= 3 && be_isstring(vm, 2) && be_isstring(vm, 3)) { #ifdef USE_BERRY_WEBCLIENT_ASYNC AsyncHttpClientLight * cl = wc_getclient(vm); #else diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino index a578042e0..dfa96038b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino @@ -316,7 +316,7 @@ extern "C" { extern const be_ctypes_structure_t be_zigbee_zcl_attribute_struct = { sizeof(Z_attribute), /* size in bytes */ - 11, /* number of elements */ + 12, /* number of elements, elements are in sorted order */ nullptr, (const be_ctypes_structure_item_t[12]) { { "_attr_id", offsetof(Z_attribute, attr_id), 0, 0, ctypes_u16, 0 },