max_input_vars trigger detection

  110062
May 7, 2020 08:55 come.chilliet@fusiondirectory.org (=?ISO-8859-1?Q?C=F4me?= Chilliet)
Hello,

We’ve hit the max_input_vars limit some time ago, and at first I tried to detect this case, but I failed as there is no handy way to detect this situation.
In our case the application was complaining about CSRF token missing since the token was truncated, and you had to go see the logs to actually see the max_input_vars error.

For those not familiar with this ini setting, it defines a maximum number of input vars in either $_GET, $_POST or $_COOKIE. Additional variables are discarded. This is a good idea to avoid attacks sending lots of data, but the program has no way of knowing it’s working with a truncated $_POST, $_GET or $_COOKIE. 

Source: https://www.php.net/manual/en/info.configuration.php#ini.max-input-vars

In the end we reworked the application to prevent it from creating a form with more than 1000 inputs as it makes no sense and is not usable.

But still, it bugs me that there is no way to programmatically know that this limit was triggered.
With recent work into error handling a lot of what was warnings or fatal errors before is now easy to catch and treat properly. It would make sense to me that this also becomes something the program can react to.

So, would it be possible either to change the warning into some kind of catchable error (but I’m not sure which operation would trigger it? Maybe first access to $_POST (in case it’s POST which triggers the limit)?),
 or to add a flag, or a function to test whether this limit was triggered.
Like was_max_input_vars_reached($_POST) ? (or was_max_input_vars_reached(POST) with an enum)

-- 
Côme Chilliet
FusionDirectory - https://www.fusiondirectory.org
  110105
May 10, 2020 12:34 php@duncanc.co.uk (Craig Duncan)
> > Although not particularly elegant, and it does require you to reject requests that hit but don't exceed the limit, I've used this approach
before: $max = ini_get("max_input_vars") - 1; $check = count($_REQUEST); if ($check > $max) { throw new RequestException("Request is too large, only {$max} input variables are permitted"); }
  110106
May 10, 2020 13:02 david.proweb@gmail.com (David Rodrigues)
Maybe throw an exception by default when it happen. Considering
max_input_vars+1, when hit, throw.

Em dom, 10 de mai de 2020 09:34, Craig Duncan <php@duncanc.co.uk> escreveu:

> > > > Although not particularly elegant, and it does require you to reject > requests that hit but don't exceed the limit, I've used this approach > before: > > > $max = ini_get("max_input_vars") - 1; > $check = count($_REQUEST); > if ($check > $max) { > throw new RequestException("Request is too large, only {$max} input > variables are permitted"); > } >
  110150
May 13, 2020 09:47 come.chilliet@fusiondirectory.org (=?UTF-8?B?Q8O0bWU=?= Chilliet)
Le Sun, 10 May 2020 13:34:12 +0100,
Craig Duncan <php@duncanc.co.uk> a écrit :
> Although not particularly elegant, and it does require you to > reject > requests that hit but don't exceed the limit, I've used this approach > before: > > $max = ini_get("max_input_vars") - 1; > $check = count($_REQUEST); > if ($check > $max) { > throw new RequestException("Request is too large, only {$max} > input variables are permitted"); > }
This is not even correct if I’m not mistaken, as max_input_vars applies independently to GET, POST and COOKIE as I understand it. Here with max_input_vars/2 in GET and POST your exception would throw while the limit was not hit. I know this is a corner case, but it’s just to illustrate it’s hard to detect whether this limit was hit and it would be better in my opinion to have a clean way in core.