-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Description
On my node (running the latest core version as of yesterday), I have really low free RAM, but this may also happen on nodes with more fragmented memory or for long POST requests.
What I'm seeing is that when submitting form data, not all form elements will be complete.
As far as I know there is no easy check to see if the web arg parsing was successful.
ESP8266WebServerTemplate<ServerType>::_parseArgumentsPrivate
does seem to parse the form data and create an array of _currentArgs
containing a key and value string.
So far so good, but sometimes I am missing a key or its value is incomplete.
The storeArgHandler
handler given to this parser function would be the ideal place to check if a result was successful, since it does know how long the strings should be when stored.
The ESP8266WebServerTemplate<ServerType>::urlDecode
function should be changed to not return a String, but filling one and also be responsible of calling reserve as soon as it knows how long the string will be. (will cause less heap fragmentation also, but may need to check the string twice)
This will make it quite clear very soon if an alloc (after calling the reserve()
) was successful.
If not, then there is no use to continue.
So it does also make sense to return a bool.
This makes it also clear void operator() (String& key, String& value, const String& data, int equal_index, int pos, int key_end_pos, int next_index)
should return a bool.
ESP8266WebServerTemplate<ServerType>::_parseArgumentsPrivate
should then return -1 on an error and its result should be dealt with here:
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::_parseArguments(const String& data) {
if (_currentArgs)
delete[] _currentArgs;
_currentArgCount = _parseArgumentsPrivate(data, nullArgHandler());
// allocate one more, this is needed because {"plain": plainBuf} is always added
_currentArgs = new RequestArgument[_currentArgCount + 1];
(void)_parseArgumentsPrivate(data, storeArgHandler<ServerType>());
}
While we're at it, I also noticed the _parseArgumentsPrivate
function is also called with a nullArgHandler
, to determine the number of arguments.
It calls this handler using this code:
RequestArgument& arg = _currentArgs[arg_total];
handler(arg.key, arg.value, data, equal_index, pos, key_end_pos, next_index);
But _currentArgs
is deleted (though not set to nullptr
).
Can this cause a crash when the former address for _currentArgs
is been re-used for something else and we're addressing it like this?
I do get the use of a nullArgHandler
, but wouldn't it make more sense to use it as a pointer which can be null? Then we can test for it and not address an array which has just been deleted.
A last point I was wondering.
Is it needed to store the plain
form element, which does contain the same information as was submitted?
If so, then wouldn't it make more sense to just store the offsets in this plain string (& decoded length) and decode it again as soon as an element is requested?
Now the data is stored twice in memory.