Cannot use string offset as an array



  • Got a couple of PHP fatal errors running:
    2.1-BETA0 (i386)
    built on Tue Jul 3 17:55:06 EDT 2012

    PHP Errors:
    [06-Jul-2012 02:43:43 UTC] PHP Fatal error:  Cannot use string offset as an array in /usr/local/www/widgets/widgets/services_status.widget.php on line 137
    [06-Jul-2012 02:44:57 UTC] PHP Fatal error:  Cannot use string offset as an array in /usr/local/www/status_services.php on line 344
    [06-Jul-2012 07:04:00 UTC] PHP Fatal error:  Cannot use string offset as an array in /usr/local/www/widgets/widgets/services_status.widget.php on line 137
    

    These are lines with "[ 0 ]" array references in them - e.g.

    if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
    

    I imagine that simply taking the "[ 0 ]" out will fix it. I guess the latest PHP 5.3.14 that is in July builds is complaining about this, but previous PHP builds did not?
    I could easily submit the changes in Github, but it would be good for someone who understands why the "[ 0 ]" was there in the first place to work out what is going on and why.
    Note: there were a few of these "[ 0 ]" removed in pfblocker code a few weeks ago. There might be lots of them through the code that need attention once the behaviour is understood.



  • I have another pfSense on exactly the same snapshot. It has WAN+OPT1 dual ISP connections, the same style of OpenVPN connections, neither box has any miniupnpd in the config. One box throws the errors above, the other one displays services and the services widget without a problem. It is rather strange.



  • The syntax is likely correct, it is just that the code is probably not checking to make sure it is an array before attempting to access members of the array.



  • Can you post the output of

    var_dump($config['installedpackages']['miniupnpd']);
    

    (Diagnostics -> Command Prompt: PHP Execute)

    I'm wondering if the whole miniupnpd section is missing or just the config part.

    Edit:
    Just proposed a patch that fixes the case where the whole miniupnp section is missing.



  • Yep, there is a difference between the system that generates the error and the "good" system:

    Error system:

    var_dump($config['installedpackages']['miniupnpd']);
    string(0) ""
    

    Good system:

    var_dump($config['installedpackages']['miniupnpd']);
    NULL
    

    On the error system I had been testing out the problems with deleting packages and have ended up with no packages installed. config.xml installed packages section looks like this:
    Error system:

    	 <installedpackages></installedpackages> 
    

    Good system:

    	 <installedpackages><pfblocker><config><donation></donation></config></pfblocker> 
    
    <menu>
    			<name>pfBlocker</name>
    			<tooltiptext>Configure pfblocker</tooltiptext>
    			Firewall
    			<url>/pkg_edit.php?xml=pfblocker.xml</url>
    		</menu></installedpackages> 
    
    

    The good system understands that 'miniupnpd' is an array key inside 'installedpackages' that happens to not exist (NULL).
    Most people have a package or 3 on their systems. But this type of bug might be an issue on new vanilla installs without any packages.



  • I just applied the 2 1-line patches at https://github.com/bsdperimeter/pfsense/commit/3392eba9e8d7925c751a7f46a3b33f904eda9a2e - it works, both the services status page and widget are fixed - thanks.



  • Mm.. strange, the patch shouldn't have fixed it as the empty string should also pass the test.
    But I don't see how an empty installedpackages section could return an empty string for a package.

    If you executevar_dump($config['installedpackages']['miniupnpd']);or even```
    var_dump($config['installedpackages']);



  • Here is the output of 4 variations:

    var_dump($config['installedpackages']['miniupnpd']);
    string(0) ""
    var_dump(isset($config['installedpackages']['miniupnpd']));
    bool(false)
    var_dump($config['installedpackages']);
    string(0) ""
    var_dump(isset($config['installedpackages']));
    bool(true)
    
    

    $config['installedpackages'] seems to really be set to the empty string.
    $config['installedpackages']['miniupnpd'] gets interpreted as $config['installedpackages'][0] - PHP thinks that the string key needs to be a numeric string index in this case and makes it 0. When the string is blank, then each offset returns blank, I can even feed in $config['installedpackages'][999] and it tells me it is a blank string. This behaviour happens when using what you intend to be an array key, but the actual variable is a string.
    But when you check with isset, it really looks at the string keys you supply and realises that you must mean that these should be array keys, not string offsets. So it returns true or false based on the existence of the array entries.

    Just for fun, PHP does not think any of these are arrays:

    var_dump(is_array($config['installedpackages']['miniupnpd']));
    bool(false)
    var_dump(is_array($config['installedpackages']));
    bool(false)
    
    

    You could also test with is_array($config['installedpackages']['miniupnpd']) - because the following code is only to be executed if this is an array.


Locked