Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
3f89271
[core][opentherm] Add format_bin_to(), soft-deprecate format_bin() (#…
bdraco Jan 17, 2026
b25a2f8
[infrared][web_server] Implement initial `web_server` support (#13202)
kbx81 Jan 17, 2026
d31b733
[light] Store color mode JSON strings in flash on ESP8266 (#13314)
bdraco Jan 17, 2026
e4fb698
[web_server] Use ESPHOME_F for canHandle domain checks to reduce ESP8…
bdraco Jan 17, 2026
4d4283b
[udp] Store addresses in flash instead of heap (#13330)
bdraco Jan 18, 2026
0a1e7ee
[pipsolar] Store command strings in flash (#13336)
bdraco Jan 18, 2026
ee2a819
[sun] Store text sensor format string in flash (#13335)
bdraco Jan 18, 2026
ed58b93
[template] Store text initial_value in flash and avoid heap allocatio…
bdraco Jan 18, 2026
4cc0f87
[wireguard] Store configuration strings in flash instead of heap (#13…
bdraco Jan 18, 2026
d6a0c8f
[template] Store alarm control panel codes in flash instead of heap (…
bdraco Jan 18, 2026
01cdc4e
[core] Add fnv1_hash_extend() string overloads, use in atm90e32 (#13326)
bdraco Jan 18, 2026
7282362
[weikai] Replace bitset to_string with format_bin_to (#13297)
bdraco Jan 18, 2026
21794e2
[modbus_controller] Use stack buffers instead of heap-allocating stri…
bdraco Jan 18, 2026
db0b32b
[network] Fix IPAddress::str_to() to lowercase IPv6 hex digits (#13325)
bdraco Jan 18, 2026
680e92a
[core] Add str_endswith_ignore_case to avoid heap allocation in audio…
bdraco Jan 18, 2026
baf2b0e
[api] Fix truncation of Home Assistant attributes longer than 255 cha…
bdraco Jan 19, 2026
1a55254
[status] Convert to PollingComponent to reduce CPU usage (#13342)
bdraco Jan 19, 2026
b44727a
[socket] Eliminate heap allocations in set_sockaddr() (#13228)
bdraco Jan 19, 2026
2f7270c
[uart] Replace unsafe sprintf with buf_append_printf in debugger (#13…
bdraco Jan 19, 2026
7b0db65
[rc522_spi] Replace unsafe sprintf with buf_append_printf (#13291)
bdraco Jan 19, 2026
052b05d
[tuya] Replace unsafe sprintf with snprintf in light color formatting…
bdraco Jan 19, 2026
5b92d0b
[wiegand] Replace heap-allocating to_string with stack buffers (#13294)
bdraco Jan 19, 2026
0f3bac5
[nextion] Replace to_string with stack buffer and fix unsafe sprintf …
bdraco Jan 19, 2026
eb66429
[sml] Use stack buffers instead of str_sprintf (#13222)
bdraco Jan 19, 2026
f60c03e
[syslog] Use buf_append_printf for ESP8266 flash optimization (#13286)
bdraco Jan 19, 2026
67871a1
[ccs811] Use buf_append_printf for buffer safety and ESP8266 flash op…
bdraco Jan 19, 2026
226867b
[esp8266] Use direct SDK calls instead of Arduino ESP class wrappers …
bdraco Jan 19, 2026
6cbe672
[tuya] Use buf_append_printf for ESP8266 flash optimization (#13287)
bdraco Jan 19, 2026
635983f
[uptime] Use buf_append_printf for ESP8266 flash optimization (#13282)
bdraco Jan 19, 2026
d8849b1
[gpio] Use buf_append_printf in dump_summary for ESP8266 flash optimi…
bdraco Jan 19, 2026
3182222
[esp32_hosted] Use stack buffer instead of str_sprintf for version st…
bdraco Jan 19, 2026
ea0fac9
[core][mqtt] Add str_sanitize_to(), soft-deprecate str_sanitize() (#1…
bdraco Jan 19, 2026
dfbf79d
[homeassistant] Use buf_append_printf for ESP8266 flash optimization …
bdraco Jan 19, 2026
d9fc625
[web_server] Simplify datetime formatting with buf_append_printf (#13…
bdraco Jan 19, 2026
b9e72a8
[daikin_arc] Fix undefined behavior in sprintf calls (#13279)
bdraco Jan 19, 2026
98ccab8
[tormatic] Use stack buffers instead of str_sprintf in debug methods …
bdraco Jan 19, 2026
8142f5d
[zephyr] Avoid heap allocation in preferences key formatting (#13215)
bdraco Jan 19, 2026
e40201a
[cse7766] Use stack buffer for verbose debug logging (#13217)
bdraco Jan 19, 2026
126190d
[ezo] Replace str_sprintf with stack-based formatting (#13218)
bdraco Jan 19, 2026
f453a8d
[dfrobot_sen0395] Reduce heap allocations in command building (#13219)
bdraco Jan 19, 2026
e99dbe0
[toshiba] Replace to_string with stack buffer in debug logging (#13296)
bdraco Jan 19, 2026
e80a940
[gdk101] Use stack buffer to eliminate heap allocation for firmware v…
bdraco Jan 19, 2026
d8a28f6
[scheduler] Replace resize() with erase() to save ~ 436 bytes flash (…
bdraco Jan 19, 2026
86a1b4c
[select][fan] Use StringRef for on_value/on_preset_set triggers to av…
bdraco Jan 19, 2026
bfcc0e2
[dfrobot_sen0395][pipsolar][sim800l][wl_134] Replace sprintf with snp…
bdraco Jan 19, 2026
f8bd4ef
[template][event] Use StringRef for set_action and on_event triggers …
bdraco Jan 19, 2026
892e9b0
[api] Use MAX_STATE_LEN constant for Home Assistant state buffer (#13…
bdraco Jan 19, 2026
ee264d0
[anova] Replace sprintf with bounds-checked alternatives (#13303)
bdraco Jan 19, 2026
a0d3d54
[mipi_spi] Add variants of ESP32-2432S028 displays (#13340)
clydebarrow Jan 19, 2026
520e69b
[serial_channel] Add a new entity type
clydebarrow Jan 19, 2026
e3638ac
Fix can_handle
clydebarrow Jan 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions esphome/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
JsonObjectConst,
Parented,
PollingComponent,
StringRef,
arduino_json_ns,
bool_,
const_char_ptr,
Expand Down
18 changes: 9 additions & 9 deletions esphome/components/anova/anova_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,57 +18,57 @@ AnovaPacket *AnovaCodec::clean_packet_() {

AnovaPacket *AnovaCodec::get_read_device_status_request() {
this->current_query_ = READ_DEVICE_STATUS;
sprintf((char *) this->packet_.data, "%s", CMD_READ_DEVICE_STATUS);
snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_DEVICE_STATUS);
return this->clean_packet_();
}

AnovaPacket *AnovaCodec::get_read_target_temp_request() {
this->current_query_ = READ_TARGET_TEMPERATURE;
sprintf((char *) this->packet_.data, "%s", CMD_READ_TARGET_TEMP);
snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_TARGET_TEMP);
return this->clean_packet_();
}

AnovaPacket *AnovaCodec::get_read_current_temp_request() {
this->current_query_ = READ_CURRENT_TEMPERATURE;
sprintf((char *) this->packet_.data, "%s", CMD_READ_CURRENT_TEMP);
snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_CURRENT_TEMP);
return this->clean_packet_();
}

AnovaPacket *AnovaCodec::get_read_unit_request() {
this->current_query_ = READ_UNIT;
sprintf((char *) this->packet_.data, "%s", CMD_READ_UNIT);
snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_UNIT);
return this->clean_packet_();
}

AnovaPacket *AnovaCodec::get_read_data_request() {
this->current_query_ = READ_DATA;
sprintf((char *) this->packet_.data, "%s", CMD_READ_DATA);
snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_DATA);
return this->clean_packet_();
}

AnovaPacket *AnovaCodec::get_set_target_temp_request(float temperature) {
this->current_query_ = SET_TARGET_TEMPERATURE;
if (this->fahrenheit_)
temperature = ctof(temperature);
sprintf((char *) this->packet_.data, CMD_SET_TARGET_TEMP, temperature);
snprintf((char *) this->packet_.data, sizeof(this->packet_.data), CMD_SET_TARGET_TEMP, temperature);
return this->clean_packet_();
}

AnovaPacket *AnovaCodec::get_set_unit_request(char unit) {
this->current_query_ = SET_UNIT;
sprintf((char *) this->packet_.data, CMD_SET_TEMP_UNIT, unit);
snprintf((char *) this->packet_.data, sizeof(this->packet_.data), CMD_SET_TEMP_UNIT, unit);
return this->clean_packet_();
}

AnovaPacket *AnovaCodec::get_start_request() {
this->current_query_ = START;
sprintf((char *) this->packet_.data, CMD_START);
snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_START);
return this->clean_packet_();
}

AnovaPacket *AnovaCodec::get_stop_request() {
this->current_query_ = STOP;
sprintf((char *) this->packet_.data, CMD_STOP);
snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_STOP);
return this->clean_packet_();
}

Expand Down
19 changes: 9 additions & 10 deletions esphome/components/api/api_connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent) : parent_(parent) {
#if defined(USE_API_PLAINTEXT) && defined(USE_API_NOISE)
auto &noise_ctx = parent->get_noise_ctx();
if (noise_ctx.has_psk()) {

Check failure on line 106 in esphome/components/api/api_connection.cpp

View workflow job for this annotation

GitHub Actions / Run script/clang-tidy for ESP8266

if with identical then and else branches
this->helper_ = std::unique_ptr<APIFrameHelper>{new APINoiseFrameHelper(std::move(sock), noise_ctx)};
} else {
this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))};
Expand Down Expand Up @@ -1712,17 +1712,16 @@
}

// Create null-terminated state for callback (parse_number needs null-termination)
// HA state max length is 255, so 256 byte buffer covers all cases
char state_buf[256];
size_t copy_len = msg.state.size();
if (copy_len >= sizeof(state_buf)) {
copy_len = sizeof(state_buf) - 1; // Truncate to leave space for null terminator
// HA state max length is 255 characters, but attributes can be much longer
// Use stack buffer for common case (states), heap fallback for large attributes
size_t state_len = msg.state.size();
SmallBufferWithHeapFallback<MAX_STATE_LEN + 1> state_buf_alloc(state_len + 1);
char *state_buf = reinterpret_cast<char *>(state_buf_alloc.get());
if (state_len > 0) {
memcpy(state_buf, msg.state.c_str(), state_len);
}
if (copy_len > 0) {
memcpy(state_buf, msg.state.c_str(), copy_len);
}
state_buf[copy_len] = '\0';
it.callback(StringRef(state_buf, copy_len));
state_buf[state_len] = '\0';
it.callback(StringRef(state_buf, state_len));
}
}
#endif
Expand Down
9 changes: 6 additions & 3 deletions esphome/components/atm90e32/atm90e32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,14 @@ void ATM90E32Component::setup() {

if (this->enable_offset_calibration_) {
// Initialize flash storage for offset calibrations
uint32_t o_hash = fnv1_hash(std::string("_offset_calibration_") + this->cs_summary_);
uint32_t o_hash = fnv1_hash("_offset_calibration_");
o_hash = fnv1_hash_extend(o_hash, this->cs_summary_);
this->offset_pref_ = global_preferences->make_preference<OffsetCalibration[3]>(o_hash, true);
this->restore_offset_calibrations_();

// Initialize flash storage for power offset calibrations
uint32_t po_hash = fnv1_hash(std::string("_power_offset_calibration_") + this->cs_summary_);
uint32_t po_hash = fnv1_hash("_power_offset_calibration_");
po_hash = fnv1_hash_extend(po_hash, this->cs_summary_);
this->power_offset_pref_ = global_preferences->make_preference<PowerOffsetCalibration[3]>(po_hash, true);
this->restore_power_offset_calibrations_();
} else {
Expand All @@ -183,7 +185,8 @@ void ATM90E32Component::setup() {

if (this->enable_gain_calibration_) {
// Initialize flash storage for gain calibration
uint32_t g_hash = fnv1_hash(std::string("_gain_calibration_") + this->cs_summary_);
uint32_t g_hash = fnv1_hash("_gain_calibration_");
g_hash = fnv1_hash_extend(g_hash, this->cs_summary_);
this->gain_calibration_pref_ = global_preferences->make_preference<GainCalibration[3]>(g_hash, true);
this->restore_gain_calibrations_();

Expand Down
8 changes: 3 additions & 5 deletions esphome/components/audio/audio_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,18 +185,16 @@ esp_err_t AudioReader::start(const std::string &uri, AudioFileType &file_type) {
return err;
}

std::string url_string = str_lower_case(url);

if (str_endswith(url_string, ".wav")) {
if (str_endswith_ignore_case(url, ".wav")) {
file_type = AudioFileType::WAV;
}
#ifdef USE_AUDIO_MP3_SUPPORT
else if (str_endswith(url_string, ".mp3")) {
else if (str_endswith_ignore_case(url, ".mp3")) {
file_type = AudioFileType::MP3;
}
#endif
#ifdef USE_AUDIO_FLAC_SUPPORT
else if (str_endswith(url_string, ".flac")) {
else if (str_endswith_ignore_case(url, ".flac")) {
file_type = AudioFileType::FLAC;
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions esphome/components/ccs811/ccs811.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ void CCS811Component::setup() {
bootloader_version, application_version);
if (this->version_ != nullptr) {
char version[20]; // "15.15.15 (0xffff)" is 17 chars, plus NUL, plus wiggle room
sprintf(version, "%d.%d.%d (0x%02x)", (application_version >> 12 & 15), (application_version >> 8 & 15),
(application_version >> 4 & 15), application_version);
buf_append_printf(version, sizeof(version), 0, "%d.%d.%d (0x%02x)", (application_version >> 12 & 15),
(application_version >> 8 & 15), (application_version >> 4 & 15), application_version);
ESP_LOGD(TAG, "publishing version state: %s", version);
this->version_->publish_state(version);
}
Expand Down
2 changes: 1 addition & 1 deletion esphome/components/ch422g/ch422g.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ bool CH422GGPIOPin::digital_read() { return this->parent_->digital_read(this->pi

void CH422GGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value ^ this->inverted_); }
size_t CH422GGPIOPin::dump_summary(char *buffer, size_t len) const {
return snprintf(buffer, len, "EXIO%u via CH422G", this->pin_);
return buf_append_printf(buffer, len, 0, "EXIO%u via CH422G", this->pin_);
}
void CH422GGPIOPin::set_flags(gpio::Flags flags) {
flags_ = flags;
Expand Down
16 changes: 10 additions & 6 deletions esphome/components/cse7766/cse7766.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,20 +207,24 @@ void CSE7766Component::parse_data_() {

#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
{
std::string buf = "Parsed:";
// Buffer: 7 + 15 + 33 + 15 + 25 = 95 chars max + null, rounded to 128 for safety margin.
// Float sizes with %.4f can be up to 11 chars for large values (e.g., 999999.9999).
char buf[128];
size_t pos = buf_append_printf(buf, sizeof(buf), 0, "Parsed:");
if (have_voltage) {
buf += str_sprintf(" V=%fV", voltage);
pos = buf_append_printf(buf, sizeof(buf), pos, " V=%.4fV", voltage);
}
if (have_current) {
buf += str_sprintf(" I=%fmA (~%fmA)", current * 1000.0f, calculated_current * 1000.0f);
pos = buf_append_printf(buf, sizeof(buf), pos, " I=%.4fmA (~%.4fmA)", current * 1000.0f,
calculated_current * 1000.0f);
}
if (have_power) {
buf += str_sprintf(" P=%fW", power);
pos = buf_append_printf(buf, sizeof(buf), pos, " P=%.4fW", power);
}
if (energy != 0.0f) {
buf += str_sprintf(" E=%fkWh (%u)", energy, cf_pulses);
buf_append_printf(buf, sizeof(buf), pos, " E=%.4fkWh (%u)", energy, cf_pulses);
}
ESP_LOGVV(TAG, "%s", buf.c_str());
ESP_LOGVV(TAG, "%s", buf);
}
#endif
}
Expand Down
21 changes: 12 additions & 9 deletions esphome/components/daikin_arc/daikin_arc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,9 @@ bool DaikinArcClimate::parse_state_frame_(const uint8_t frame[]) {
}

char buf[DAIKIN_STATE_FRAME_SIZE * 3 + 1] = {0};
size_t pos = 0;
for (size_t i = 0; i < DAIKIN_STATE_FRAME_SIZE; i++) {
sprintf(buf, "%s%02x ", buf, frame[i]);
pos = buf_append_printf(buf, sizeof(buf), pos, "%02x ", frame[i]);
}
ESP_LOGD(TAG, "FRAME %s", buf);

Expand Down Expand Up @@ -349,8 +350,9 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) {
if (data.expect_item(DAIKIN_HEADER_MARK, DAIKIN_HEADER_SPACE)) {
valid_daikin_frame = true;
size_t bytes_count = data.size() / 2 / 8;
std::unique_ptr<char[]> buf(new char[bytes_count * 3 + 1]);
buf[0] = '\0';
size_t buf_size = bytes_count * 3 + 1;
std::unique_ptr<char[]> buf(new char[buf_size]()); // value-initialize (zero-fill)
size_t buf_pos = 0;
for (size_t i = 0; i < bytes_count; i++) {
uint8_t byte = 0;
for (int8_t bit = 0; bit < 8; bit++) {
Expand All @@ -361,19 +363,19 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) {
break;
}
}
sprintf(buf.get(), "%s%02x ", buf.get(), byte);
buf_pos = buf_append_printf(buf.get(), buf_size, buf_pos, "%02x ", byte);
}
ESP_LOGD(TAG, "WHOLE FRAME %s size: %d", buf.get(), data.size());
}
if (!valid_daikin_frame) {
char sbuf[16 * 10 + 1];
sbuf[0] = '\0';
char sbuf[16 * 10 + 1] = {0};
size_t sbuf_pos = 0;
for (size_t j = 0; j < static_cast<size_t>(data.size()); j++) {
if ((j - 2) % 16 == 0) {
if (j > 0) {
ESP_LOGD(TAG, "DATA %04x: %s", (j - 16 > 0xffff ? 0 : j - 16), sbuf);
}
sbuf[0] = '\0';
sbuf_pos = 0;
}
char type_ch = ' ';
// debug_tolerance = 25%
Expand Down Expand Up @@ -401,9 +403,10 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) {
type_ch = '0';

if (abs(data[j]) > 100000) {
sprintf(sbuf, "%s%-5d[%c] ", sbuf, data[j] > 0 ? 99999 : -99999, type_ch);
sbuf_pos = buf_append_printf(sbuf, sizeof(sbuf), sbuf_pos, "%-5d[%c] ", data[j] > 0 ? 99999 : -99999, type_ch);
} else {
sprintf(sbuf, "%s%-5d[%c] ", sbuf, (int) (round(data[j] / 10.) * 10), type_ch);
sbuf_pos =
buf_append_printf(sbuf, sizeof(sbuf), sbuf_pos, "%-5d[%c] ", (int) (round(data[j] / 10.) * 10), type_ch);
}
if (j + 1 == static_cast<size_t>(data.size())) {
ESP_LOGD(TAG, "DATA %04x: %s", (j - 8 > 0xffff ? 0 : j - 8), sbuf);
Expand Down
29 changes: 19 additions & 10 deletions esphome/components/dfrobot_sen0395/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,20 @@ DetRangeCfgCommand::DetRangeCfgCommand(float min1, float max1, float min2, float
this->min2_ = min2 = this->max2_ = max2 = this->min3_ = min3 = this->max3_ = max3 = this->min4_ = min4 =
this->max4_ = max4 = -1;

this->cmd_ = str_sprintf("detRangeCfg -1 %.0f %.0f", min1 / 0.15, max1 / 0.15);
char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f", min1 / 0.15, max1 / 0.15);
this->cmd_ = buf;
} else if (min3 < 0 || max3 < 0) {
this->min1_ = min1 = round(min1 / 0.15) * 0.15;
this->max1_ = max1 = round(max1 / 0.15) * 0.15;
this->min2_ = min2 = round(min2 / 0.15) * 0.15;
this->max2_ = max2 = round(max2 / 0.15) * 0.15;
this->min3_ = min3 = this->max3_ = max3 = this->min4_ = min4 = this->max4_ = max4 = -1;

this->cmd_ = str_sprintf("detRangeCfg -1 %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15, min2 / 0.15, max2 / 0.15);
char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15, min2 / 0.15,
max2 / 0.15);
this->cmd_ = buf;
} else if (min4 < 0 || max4 < 0) {
this->min1_ = min1 = round(min1 / 0.15) * 0.15;
this->max1_ = max1 = round(max1 / 0.15) * 0.15;
Expand All @@ -145,9 +150,10 @@ DetRangeCfgCommand::DetRangeCfgCommand(float min1, float max1, float min2, float
this->max3_ = max3 = round(max3 / 0.15) * 0.15;
this->min4_ = min4 = this->max4_ = max4 = -1;

this->cmd_ = str_sprintf("detRangeCfg -1 "
"%.0f %.0f %.0f %.0f %.0f %.0f",
min1 / 0.15, max1 / 0.15, min2 / 0.15, max2 / 0.15, min3 / 0.15, max3 / 0.15);
char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15, min2 / 0.15,
max2 / 0.15, min3 / 0.15, max3 / 0.15);
this->cmd_ = buf;
} else {
this->min1_ = min1 = round(min1 / 0.15) * 0.15;
this->max1_ = max1 = round(max1 / 0.15) * 0.15;
Expand All @@ -158,10 +164,10 @@ DetRangeCfgCommand::DetRangeCfgCommand(float min1, float max1, float min2, float
this->min4_ = min4 = round(min4 / 0.15) * 0.15;
this->max4_ = max4 = round(max4 / 0.15) * 0.15;

this->cmd_ = str_sprintf("detRangeCfg -1 "
"%.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f",
min1 / 0.15, max1 / 0.15, min2 / 0.15, max2 / 0.15, min3 / 0.15, max3 / 0.15, min4 / 0.15,
max4 / 0.15);
char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15,
min2 / 0.15, max2 / 0.15, min3 / 0.15, max3 / 0.15, min4 / 0.15, max4 / 0.15);
this->cmd_ = buf;
}

this->min1_ = min1;
Expand Down Expand Up @@ -203,7 +209,10 @@ SetLatencyCommand::SetLatencyCommand(float delay_after_detection, float delay_af
delay_after_disappear = std::round(delay_after_disappear / 0.025f) * 0.025f;
this->delay_after_detection_ = clamp(delay_after_detection, 0.0f, 1638.375f);
this->delay_after_disappear_ = clamp(delay_after_disappear, 0.0f, 1638.375f);
this->cmd_ = str_sprintf("setLatency %.03f %.03f", this->delay_after_detection_, this->delay_after_disappear_);
// max 32: "setLatency "(11) + float(8) + " "(1) + float(8) + null, rounded to 32
char buf[32];
snprintf(buf, sizeof(buf), "setLatency %.03f %.03f", this->delay_after_detection_, this->delay_after_disappear_);
this->cmd_ = buf;
};

uint8_t SetLatencyCommand::on_message(std::string &message) {
Expand Down
8 changes: 4 additions & 4 deletions esphome/components/dfrobot_sen0395/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ class SetLatencyCommand : public Command {
class SensorCfgStartCommand : public Command {
public:
SensorCfgStartCommand(bool startup_mode) : startup_mode_(startup_mode) {
char tmp_cmd[20] = {0};
sprintf(tmp_cmd, "sensorCfgStart %d", startup_mode);
char tmp_cmd[20]; // "sensorCfgStart " (15) + "0/1" (1) + null = 17
buf_append_printf(tmp_cmd, sizeof(tmp_cmd), 0, "sensorCfgStart %d", startup_mode);
cmd_ = std::string(tmp_cmd);
}
uint8_t on_message(std::string &message) override;
Expand Down Expand Up @@ -142,8 +142,8 @@ class SensitivityCommand : public Command {
SensitivityCommand(uint8_t sensitivity) : sensitivity_(sensitivity) {
if (sensitivity > 9)
sensitivity_ = sensitivity = 9;
char tmp_cmd[20] = {0};
sprintf(tmp_cmd, "setSensitivity %d", sensitivity);
char tmp_cmd[20]; // "setSensitivity " (15) + "0-9" (1) + null = 17
buf_append_printf(tmp_cmd, sizeof(tmp_cmd), 0, "setSensitivity %d", sensitivity);
cmd_ = std::string(tmp_cmd);
};
uint8_t on_message(std::string &message) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ void Esp32HostedUpdate::setup() {
// Get coprocessor version
esp_hosted_coprocessor_fwver_t ver_info;
if (esp_hosted_get_coprocessor_fwversion(&ver_info) == ESP_OK) {
this->update_info_.current_version = str_sprintf("%d.%d.%d", ver_info.major1, ver_info.minor1, ver_info.patch1);
// 16 bytes: "255.255.255" (11 chars) + null + safety margin
char buf[16];
snprintf(buf, sizeof(buf), "%d.%d.%d", ver_info.major1, ver_info.minor1, ver_info.patch1);
this->update_info_.current_version = buf;
} else {
this->update_info_.current_version = "unknown";
}
Expand Down
16 changes: 8 additions & 8 deletions esphome/components/esp8266/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
#include "esphome/core/helpers.h"
#include "preferences.h"
#include <Arduino.h>
#include <Esp.h>
#include <core_esp8266_features.h>

extern "C" {
#include <user_interface.h>
}

namespace esphome {

Expand All @@ -16,23 +20,19 @@ void IRAM_ATTR HOT delay(uint32_t ms) { ::delay(ms); }
uint32_t IRAM_ATTR HOT micros() { return ::micros(); }
void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); }
void arch_restart() {
ESP.restart(); // NOLINT(readability-static-accessed-through-instance)
system_restart();
// restart() doesn't always end execution
while (true) { // NOLINT(clang-diagnostic-unreachable-code)
yield();
}
}
void arch_init() {}
void IRAM_ATTR HOT arch_feed_wdt() {
ESP.wdtFeed(); // NOLINT(readability-static-accessed-through-instance)
}
void IRAM_ATTR HOT arch_feed_wdt() { system_soft_wdt_feed(); }

uint8_t progmem_read_byte(const uint8_t *addr) {
return pgm_read_byte(addr); // NOLINT
}
uint32_t IRAM_ATTR HOT arch_get_cpu_cycle_count() {
return ESP.getCycleCount(); // NOLINT(readability-static-accessed-through-instance)
}
uint32_t IRAM_ATTR HOT arch_get_cpu_cycle_count() { return esp_get_cycle_count(); }
uint32_t arch_get_cpu_freq_hz() { return F_CPU; }

void force_link_symbols() {
Expand Down
Loading
Loading