Repository navigation
fix(nvs): std::string reads no longer include the zero terminator in size() (#854) - #855
Merged
Merged
Conversation
…size() NvsHandle::get() for std::string sized the string with get_item_size(), which for strings counts the zero terminator (IDF documents this), and get_string() then wrote that terminator into the string: a stored "ABCDEFG" came back with size() 8 and a trailing '\0', so comparisons failed and serialised output carried an embedded NUL. Both std::string read overloads (plain, and with a default value) now drop the terminator after a successful read, so size() is the stored string's length. Nothing else changes: the generic / bool / float paths and the string write path are untouched. The example prints the size next to each string it reads back. Fixes #854 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
|
✅Static analysis result - no issues found! ✅ |
…mmary Append a validation section to the nvs example that exercises integer, bool, float and string round trips through get_or_set_var / set_var / get_var plus key and namespace erase, with explicit pass / fail checks and a final "N/M checks passed" summary. The string checks assert that size() is the stored string's length (no zero terminator in the value, #854). The checks run in their own namespace that is erased before and after, so every boot runs the same sequence. Documented in the example README. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
… validation `s == "default"` already compares the size, so the explicit `s.size() == N` next to it is always true once the equality holds (knownConditionTrueFalse). The 64-character and `strlen(c_str()) == size()` checks still assert the #854 property directly. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #854.
NvsHandle::get()forstd::stringsized the string withget_item_size(), which for strings counts the zero terminator (IDF documents this onget_item_size), andget_string()then wrote that terminator into the string. A stored"ABCDEFG"came back withsize() == 8and a trailing'\0', so==/compare()failed and serialised output carried an embedded NUL, exactly as reported.The change is confined to the two
std::stringread overloads innvs_handle_espp.hpp(get(key, std::string&, ec)andget(key, std::string&, default, ec), whichNvs::get_var/get_or_set_vardispatch to): after a successfulget_string()the string is resized tolen - 1, sosize()is the stored string's length. The generic /bool/floatpaths and the string write path are untouched; the default-value branch still assigns the default unchanged. The doc comments say whatsize()now means, and the example prints the size next to each string it reads back.Example validation section
The nvs example now ends with a self-check section (
//! [nvs validation]) that exercises the NVS operations with explicit pass / fail checks and prints a summary (NVS validation: 18/18 checks passed - PASS, failing checks listed after it). It runs in its ownvalidatenamespace that is erased before and after, so every boot runs the same sequence:get_or_set_var(missing key stores and returns the default) andset_var/get_varsize()and last character, shorter overwrite into a longer destination, empty string, 64-character string,strlen(c_str()) == size(), no embedded'\0'The string checks are the regression test for #854: before the fix,
size()is one too large and the equality checks fail.Test plan
components/nvs/examplebuilds for esp32 (IDF 6.1) and esp32p4String = 'default' (7 bytes)on first boot andString = 'hello' (5 bytes)after the set; the reporter'stest_NVS()printssize=7for both readsNVS validation: 18/18 checks passed - PASS🤖 Generated with Claude Code
https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU