Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maximum string length of 13 characters #2093

Closed
DWilhelmLKKS opened this issue May 16, 2024 · 2 comments
Closed

Maximum string length of 13 characters #2093

DWilhelmLKKS opened this issue May 16, 2024 · 2 comments
Labels

Comments

@DWilhelmLKKS
Copy link

DWilhelmLKKS commented May 16, 2024

Describe the issue
I'm trying to read some texts out of my JSON file but when strings become longer than 13 characters I just get data junk.

Troubleshooter report
Here is the report generated by the ArduinoJson Troubleshooter:
Well, I'm out of ideas: you need to talk to a human.

Environment
Here is the environment that I'm using':

  • Microconroller: ESP32S3 (WT32-SC01 Plus)
  • IDE: Arduino IDE 2.3.2
  • ArduinoJson v7.0.4

Reproduction
Here is a small snippet that demonstrate the problem.

JsonObject root = jsonDocument.as<JsonObject>();
uint16_t i = 0;

for (JsonPair pair : root) {
  JsonObject object = pair.value().as<JsonObject>();

  Remote remote;
  remote.link         = object[KEY_LINK].as<String>();
  remote.manufacturer = object[KEY_MANUFACTURER].as<String>();
  remote.serial       = String(pair.key().c_str());

  remotesList[i++] = remote;
  Serial.printf("%s / %s / %s\n", remotesList[i-1].link, remotesList[i-1].manufacturer, remotesList[i-1].serial);
}
{
  "9": {"manufacturer": "123456789", "link": "123456789"},
  "10": {"manufacturer": "1234567890", "link": "1234567890"},
  "11": {"manufacturer": "12345678901", "link": "12345678901"},
  "12": {"manufacturer": "123456789012", "link": "123456789012"},
  "13": {"manufacturer": "1234567890123", "link": "1234567890123"},
  "14": {"manufacturer": "12345678901234", "link": "12345678901234"},
  "15": {"manufacturer": "123456789012345", "link": "123456789012345"}
}

Program output
If relevant, include the program output.

Expected output:

123456789 / 123456789 / 9
1234567890 / 1234567890 / 10
12345678901 / 12345678901 / 11
123456789012 / 123456789012 / 12
1234567890123 / 1234567890123 / 13
12345678901234 / 12345678901234 / 14
123456789012345 / 123456789012345 / 15

Actual output:

123456789 / 123456789 / 9
1234567890 / 1234567890 / 10
12345678901 / 12345678901 / 11
123456789012 / 123456789012 / 12
1234567890123 / 1234567890123 / 13
���?� / ���?� / 14
@��?� / @��?� / 15

Printing the value of Serial.printf("%d\n", ArduinoJson::detail::StringNode::maxLength); returns 255 as expected.

@DWilhelmLKKS
Copy link
Author

I found the solution! It had nothing to do with ArduinoJson. :)
Using this code fixed it:

Serial.printf("%s / %s / %s\n", remotesList[i-1].link.c_str(), remotesList[i-1].manufacturer.c_str(), remotesList[i-1].serial.c_str());

@bblanchon
Copy link
Owner

Hi @DWilhelmLKKS,

I was about to tell you the same thing :-)
Indeed, printf() is a legacy of the C language and knows nothing about String and classes in general.
I don't know why they decided to integrate it into ESP32's core.

BTW, it was accidentally working with strings of 13 characters or less because of the short-string optimization (SSO) implemented in ESP32's String:

struct _ptr { 
    char *   buff;
    uint32_t cap;
    uint32_t len;
};
enum { SSOSIZE = sizeof(struct _ptr) + 4 - 1 };
struct _sso {
    char     buff[SSOSIZE];
    unsigned char len   : 7;
    unsigned char isSSO: 1;
};

This gives an SSOSIZE of 12 + 4 - 1 = 15, enough room for 14 characters and the terminator.
So, in theory, 14-character strings should have worked too, but there is an off-by-one error in the length comparison that decides whether to use SSO or not:

if (maxStrLen < sizeof(sso.buff) - 1)

It should be <= instead of <; that's why SSO doesn't work with 14-character strings.

Best regard,
Benoit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants