To mitigate denial of service attacks, PHP 5.3.9 introduced a max-input-vars configuration that defaults to 1000. This has also been backported to some 5.2.x security builds bundled with Ubuntu and other major Linux distributions.

Each menu item on the admin/structure/menu/manage/MENU_NAME form adds several POST variables of the form mlid:$i[...]. The max-input-vars value applies to each level in a multidimensional array, not to the total number of variables, so even though several subvariables within the square brackets are posted, each menu item counts as just one variable against the 1000 limit. Still, for sites with >1000 items in a menu, this results in a broken administration page.

A possible fix is to group the submitted data into partitioned subarrays, so that no single array exceeds 1000.

Comments

jurgenhaas’s picture

We just ran into this very same problem and had some internal discussions on how to approach it. Here are some thoughts:

First of all, while Drupal is generating a form, it knows the limit from max_input_vars and it knows the number of fields in the form (including the hidden ones). So we do know for sure if we deliver a form to the browser that will certainly unsubmittable (if that's a word that exists). In this case, a drupal_set_message would be extremely helpful to prevent people from pulling their hair out as they won't knwo why they get no effect when hitting that submit button.

But of course, that's no solution to the problem itself.

For us the first question was, if this is a problem purely related to admin/structure/menu/manage/MENU_NAME or if we have other areas of potential similar problems. Regarding core we can certainly think of admin/people/permissions (although a nice solution already exists: the module filter_perms) and also admin/structure/taxonomy/TAXONOMY_NAME. Everything else is usually paged and therefore prevents that huge number of form elements.

Things like "Manage Menu" and "Manage Taxonomy Terms" can not be paged as long as we want to allow that Drag&Drop functionality, which I guess is essential.

However, those pages are not really usable as they are today and maybe that's the route to take to go after both issues at the same time: usability and huge number of form elements.

Either there is a way to trim down those forms by always only displaying a subset of the whole thing and then provide clever javascript and ajax driven interactivity to change the scope dynamically or, and that's maybe the better approach, we still deliver the whole form and instead of submitting everything through the submit button, we could submit individual changes via ajax as they get changed and the server stores those changes in the cache which will then be executed when the final submit action is taken. Having said that, this second approach does not address the usability issue though.

Any thoughts on this from others?

tangent’s picture

Part of the reason that the current menu admin page is a single massive form is doubtless that reliance on AJAX, or even Javascript, would be an issue for some.

I also have this issue on the website that I manage. It is currently impossible to use the menu admin page.

The way forward may involve adding a filtering form at the top, perhaps something like the node filter form. There are a variety of filtering solutions scattered across many contrib modules to draw inspiration from though. Perhaps the filtering would only be visible above a certain number of menu items.

j0rd’s picture

Component:menu.module» ajax system

For me, I ran into this problem because of suhosin settings, which is also set to 1000. This patch as mentioned is available in versions previous to 5.3.9, for instance debian lenny.

Here's my post about this issue in Display Suite's issue queue, I explain the problem and what's it's causing Drupal to do.
#1870014: Admin Interface Fail: PHP max_input_vars & suhosin post variable limit with a node with lots of fields (50+).

Changing the component to ajax, as this is an ajax issue, and menu is a casualty of it, as is display suite.

Here are some other related core issues regarding this:
#329056: Unable to save changes to menu
#1565704: Core interfaces can go over max_input_vars

j0rd’s picture

Issue tags:+max_input_vars

tagging.

j0rd’s picture

tagging

ayalon’s picture

I searched this for hours:

If you have a menu with 250 entries, any changes to menu items will not be savedwith php 5.3.9. Every menu item has 4 post variables = 4 * 250 = 1000 variables

Change the php.ini file
max_input_vars=50000

or someting like that and restart your server daemon.

j0rd’s picture

Title:admin/structure/menu/manage/MENU_NAME cannot be submitted on PHP 5.3.9+ for large menus (>~1000 items)» admin/structure/menu/manage/MENU_NAME cannot be submitted on PHP 5.3.9+ for large menus (>~250 items)

@ayalon. You seem to be correct. Each menu item has:

mlid[123][hidden]
mlid[123][weight]
mlid[123][plid]
mlid[123][mlid]

So as you mentioned, I assume this will fail after 250 items with max_input_vars at 1000. Going to update the title & description to reflect this and hopefully we'll get more eyes on it.

UPDATE: I was in-correct after looking into this further. As mentioned in the OP, the limit applies to only each level of the _POST array.

So you can have 1000 first level items, and for each of those, you can also have another 1000 keys for a total of 1,000,000 and this will work just fine and not cause problems with max_input_vars (post_max_size is another story). This limit was put in place to avoid hash collisions. Since the form also posts form_build_id, form_token, form_id & op you're left with 996 menu items most likely.

j0rd’s picture

Title:admin/structure/menu/manage/MENU_NAME cannot be submitted on PHP 5.3.9+ for large menus (>~250 items)» admin/structure/menu/manage/MENU_NAME cannot be submitted on PHP 5.3.9+ for large menus (>~1000 items)

Changing title back. Sorry.

dman’s picture

Just to say this is still outstanding, and wasn't something I could find in searching on d.o (or anywhere) until *after* I'd fully identified the problem and knew the keywords.And came here..

It presented to me as
* Editing a large menu (close to 600 rows) with the menu UI
* submitting the form did not save, and actually complained 'The form has become outdated'

This was a 'live' server case only - as local dev did not have suhosin configs like that. At least my inability to replicate locally pointed me at the OS/settings as a culprit.

'The form has become outdated' was a real red herring of a message, but investigation led me to conclude that the POST data was getting truncated, as the token at the end of the form seemed to be getting lost.

I tried shifting the 'submit' button and hidden form values to the top of the form (abusing the theme_menu_overview_form() function) and got ... different results. This made me feel I was on the right track re truncation.

With Apache/PHP logging turned up to verbose, I found

[error] [client 127.0.0.1] PHP Warning:  Unknown: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini. in Unknown on line 0, referer: http://.../admin/structure/menu/manage/main-menu

Although I knew there was such a thing as max_post size, and soon found 'max_input_vars' - those did not fix the issue.

Only after adding

max_input_vars = 10000
[suhosin]
suhosin.post.max_vars = 10000
suhosin.request.max_vars = 10000
suhosin.post.max_array_index_length = 10000
suhosin.request.max_array_index_length = 10000

into php.ini and a HARD Apache restart did my menu start working again.

This was hard to trace!

Phew.

If your menu is too big to manage, you can try Big Menu

- which rewrites the menu admin UI to use AJAX loads (as suggested above). And therefore sidesteps this issue.
However, I'd written it to avoid UI overload, not server limitations, so didn't go straight to it in this case. We can deal with 'several hundred' items in the main architecture - I'd switch to bigmenu about the 800 mark. Or - maybe today.

datvance’s picture

Issue summary:View changes

Just to update in case someone like me finds this later and is confused, the limit applies to all levels combined...

[2012-08-24 14:03 UTC] rasmus@php.net
This is a documentation bug. The limit is across all nesting levels.

https://bugs.php.net/bug.php?id=62921