Skip to content

Request: Add success/fail flag for webserver parse arguments #6884

@TD-er

Description

@TD-er

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions