-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Some strings seem to have bogus data at the end (core 2.6.0 vs. core 2.4.2) #5883
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
Comments
@TD-er repl(F("{E}"), euro, s, useURLencode);
repl(F("€"), euro, s, useURLencode);
repl(F("{Y}"), yen, s, useURLencode);
repl(F("¥"), yen, s, useURLencode); you're passing in a F("blah") macro and a pointer to const char [] instead of references to String objects. What exactly do you expect? There is no String object anywhere for which to pass a reference into repl(). I have to wonder how this code builds at all. If repl() were to take in String args by value instead of reference, then the F() and const char[] would be implicitly cast to a String object that would be passed in. However, in this case passing in a String object would create a duplicate temp String to be passed in, which is not very good. I suggest one of the following:
template <typename keyType, typename valType>
void repl(const keyType &key, const valType &val, bool useURLencode)
{
if (useURLencode) {
s.replace(key, URLEncode(val.c_str()));
} else {
s.replace(key, val);
}
}
repl(String(F("{E}")), String(euro), s, useURLencode);
repl(String(F("€")), String(euro), s, useURLencode);
repl(String(F("{Y}")), String(yen), s, useURLencode);
repl(String(F("¥")), yen, s, useURLencode); Closing due to user error. |
I really don't understand what's wrong here. |
You have this: void repl(const String& key, const String& val, String& s, boolean useURLencode) The arg types of key and val are not String, but references to String (String &). The compiler can't convert to a reference, because there is no object that the reference can point to. If you want to go the template repl way, it may be better like so: void repl<String>
template <typename keyType, typename valType>
void repl(const keyType &key, const valType &val, bool useURLencode)
{
if (useURLencode) {
s.replace(String(key), URLEncode(val.c_str()));
} else {
s.replace(String(key), String(val));
}
} What does URLEncode() return? If something other than a String, then it needs a wrapper with a temp String obj as well. There might be a way to avoid the duplication due to the temp Strings by using std::move, but I'm not sure, I don't think I've ever seen move semantics for String being used. |
Is there some way to make the compiler not accept the automatic casts from char* (or other variants) to a |
I said:
I'd have to investigate why your code is building at all, and I won't have the bandwidth until the end of the month. One thing you could do is search for all functions that take a String & as part of its definition. Once you have function signatures, you could:
|
I've been looking into the changes of the String class: https://github.com/esp8266/Arduino/pull/5690/files Also I do not agree that this is not a bug, since it is a bug. Arduino/cores/esp8266/WString.cpp Lines 32 to 36 in d19fc3b
The code called in But the copy does: Arduino/cores/esp8266/WString.cpp Lines 203 to 211 in d19fc3b
This is calling Arduino/cores/esp8266/WString.cpp Lines 144 to 197 in d19fc3b
Not sure what would be done when not in SSO mode, but to me it looks like this internal SSO-buffer should be initialized with zeroes first before the tekst is copied. Arduino/cores/esp8266/WString.cpp Lines 164 to 168 in d19fc3b
N.B. the use of memcpy is the right choice here, but then you must make sure to have the next byte 0-terminated. I have to check it first, but I guess that initializing the array at line 164 with zeroes will get rid of these problems. char temp[sizeof(sso_buf)] = {0}; It should also lead to some issues when just creating a String with a const char* as argument. |
Just made a quick test and this does fix this issue:
I will try to look into a few more places of the code and see if some similar issues arise and als try to make some tests that are reproducible for this. |
When looking at the other parts of the code, I noticed these functions to convert a float or double to a String: Arduino/cores/esp8266/WString.cpp Lines 111 to 121 in d19fc3b
There is no check in here for the max. number of decimal places. |
A fix for some issue introduced in PR esp8266#5690 See discussion in esp8266#5883
Another note on the conversions made by the compiler. Thing is, the closing of this issue made me doubt about my C++ insights, so I asked a former colleague of mine, who quotes C++ standard section numbers like some quote bible verses and he assured me it was indeed a constructor being called. Maybe @earlephilhower can also have a look, since he made the SSO feature. (which I like a lot by the way) |
Fixes esp8266#5883 and supercedes esp8266#5890 The replace() function was using len() while in the middle of buffer operations. In SSO mode len() is not stored separately and is a call to strlen(), which may not be legal if you're in the middle of overwriting the SSO buffer, as was the case in ::replace when the replacement string was longer than the find string. This caused potential garbage at the end of the string when accessed. Instead, just cache the length in a local while doing the operation. Also make setLength() explicitly write a 0 in the SSO buffer at the specific offset. It's probably not needed, but is safe to do and makes logical sense. Add in test cases from esp8266#5890 as well as some new ones that fail on the unmodified core.
* Fix String::replace() Fixes #5883 and supercedes #5890 The replace() function was using len() while in the middle of buffer operations. In SSO mode len() is not stored separately and is a call to strlen(), which may not be legal if you're in the middle of overwriting the SSO buffer, as was the case in ::replace when the replacement string was longer than the find string. This caused potential garbage at the end of the string when accessed. Instead, just cache the length in a local while doing the operation. Add in test cases from #5890 as well as some new ones that fail on the unmodified core. * Fix stack smashing error on 64b When pointers are 8 bytes long, the size of a String is larger than 16 chars. Increase the allocated array we're using in the test to avoid a "stack smashing" error. * Manually call destructor in test Just for clarity, manually call the destructor for the Strings() that are "placement new'd" in the String tests. It is a no-op for the existing test, since thanks to SSO there are no memory allocations, but will help in case someone adds tests later which include longer strings.
In ESPeasy we have some web page rendering all kinds of variables/strings as a cheat-sheet for the internal variable substitutions.
The same code built using core 2.4.2 and core 2.6.0 (both SDK 2.2.1 and SDK 2.2.2) shows different output.
Core 2.6.0:
%ssid% MikroTik0�$ MikroTik0�$
%sysname% CO2_defect$ CO2_defect$
{E} € %e2%82%ac�$
€ € %e2%82%ac�$
Core 2.4.2:
%ssid% MikroTik MikroTik
%sysname% CO2_defect CO2_defect
{E} € %e2%82%ac
€ € %e2%82%ac
This is an example of a conversion which appears to be correct in both:
{Y} ¥ %c2%a5
¥ ¥ %c2%a5
These are the ones giving different results (may be others, but these are noticeable)
These are the result from a call to this function:
The ones that work just fine are the ones that were converted to a
String
object before calling this function.The ones that fail are all char arrays, but not all of these fail like can be seen with the "yen" conversion.
It looks like the ones that fail have an odd number of characters (e.g. the example sysname is 10 characters).
These char arrays are all 0-terminated, or else they would have given issues in core 2.4.2 too.
The ones that were converted to a String before calling this
repl
function, were probably padded with more zeroes due to how the String implementation now does its allocation.The text was updated successfully, but these errors were encountered: