Is there a way to escape `]` PHP <input name="array[with-text-keys]"> notation?

Viewed 98

I am maintaining a legacy PHP application which uses many string indexed arrays as ipnut names. There are many snippets similar to this:

<input name="<?= 
    htmlspecialchars(
        'array_name[' . $string_index . ']',
        ENT_QUOTES
    ); ?>" 
/>

This worked pretty well for a few years until someone used a_string_with[square_brackets] as $string_index.

This value broken the app as it was send to the server as:

array_name[a_string_with[square_brackets]]=value

...which was interpreted by PHP as var_dump($_POST):

array (size=1)
  'array_name' => 
    array (size=1)
      'a_string_with[square_brackets' => string 'any_value' (length=9)

Notice the missing closing square bracket ] in the array key. It seems that second square bracket (and everything that follows it) is silently ignored by php.

I have searched for a while, and could not find a way to escape the closing bracket that would be automaticly interpreted by php when parsing request.

I have decided to replace this keys with base64 encoded values, but I wonder if PHP really does not have such feature?

Minimal example Just create a file contining one php line:

<?php
var_dump($_GET);

... and call it:

http://localhost/var_dump.php?array_name[a_string_with[square_brackets]]=any_value
1 Answers

Unfortunately, it's not possible to escape this behaviour in any way. At the end of the day it is a bug in PHP, one that is difficult to eradicate since the removal of register_globals.

You can work around this in a few ways. One would be to use rawurlencode() on the $string_index and then when you receive that value in PHP you can use rawurldecode()

Another option would be to do what PHP does and replace "invalid" characters with _. Something like:

$string_index = str_replace(['[', ']', '.', ' '], '_', $string_index);

None of the above solutions are great and what's worse there are valid examples of forms in HTML that can't use such workarounds. So yeah... PHP is broken and until someone writes an RFC to fix this in PHP, we will continue to have such problems.

Related