Why is get_env() treating my boolean environment variable as a string? - php

I upgraded my Wordpress instance from 4.5 to 4.8, and for some reason my boolean environment variable is now returning as a string of "false" rather than false. Since my PHP version hasn't changed, I'm a bit mystified at the change. More importantly however, about going forward, what's the best way to manage getting booleans into PHP via environment vars?
Here's the .env line I have:
WP_FORCE_SSL_ADMIN=false
Here's the line I had in my wp-config.php that is returning true due to string conversion.
define('FORCE_SSL_ADMIN', getenv('WP_FORCE_SSL_ADMIN'));
Here's the var_dump:
["WP_FORCE_SSL_ADMIN"]=>
string(5) "false"
I know that I can simply refactor the define to account for the string conversion, but I'm bothered that I don't understand what changed when nothing should have. This worked fine on for wordpress version 4.5.
Looking for an answer to explain the best method for passing boolean vars from my environment into PHP, or do I always have to account for the string conversion?

Just in case someone comes here looking for the answer to how I solved it, what I did was simply do a comparison to the string of "true".
define('FORCE_SSL_ADMIN', strtolower(getenv('WP_FORCE_SSL_ADMIN')) === "true");
While this works, it still doesn't feel quite right to me, like I'm missing something.

Related

Why `mysqli_query()` returns null? How can i figure it out?

Under certain circumstances, the built-in function in PHP called mysqli_query returns null. Such behaviour is not foreseen by the function's documentation that explains how to use it, so I tried to dive in PHP's source code itself, posted on GitHub, to see if I can figure out why sometimes mysqli_query returns null.
The queries themselves doesn't seem to be the problem: I tested the relevant SQL queries in two different ways:
Executing them manually in the MySQL Server. They work correctly.
Within a script that I created with the single purpose of testing the queries through mysqli_query(). They work under this test, and the function returns true.
However, under certain conditions, those same queries return null. The mysqli link object exists when mysqli_query function starts running, when this "returning null failure" happens.
So, looking in the PHP's GitHub repository, i found the file called mysqli_nonapi.c and, in line 556 within this file, what seems to be the built-in mysqli_query definition. Looking at the code within, it looks like it performs a basic check and, if it fails, it returns null. Here are the first lines linked above:
/* {{{ proto mixed mysqli_query(object link, string query [,int resultmode]) */
PHP_FUNCTION(mysqli_query){
MY_MYSQL *mysql;
zval *mysql_link;
MYSQLI_RESOURCE *mysqli_resource;
MYSQL_RES *result = NULL;
char *query = NULL;
size_t query_len;
zend_long resultmode = MYSQLI_STORE_RESULT;
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|l", &mysql_link, mysqli_link_class_entry, &query, &query_len, &resultmode) == FAILURE) {
return;
}
// [...]
}
Even though I have used sometimes C code, I just know a little about C. I am aware that it uses pointers and I guess those parameters which name start with * are pointers. Anyways, I am not sure on how to interpretate this piece of code, or figuring out how it's internal flow affects PHP execution.
Long story short: I can assume somehow, the initial check shown above within the function failed for some reason. But, to find out why, I need to understand that piece of code first.
I am afraid I cannot isolate the issue to trigger the error outside production environment, which would be very useful for exhaustive testing. So, what options do I have left? Is there something I can do to debug that internal piece of code, or otherwise, figuring out why it might be failing within?
I made the tests in both PHP5 and PHP7; it fails the same way in both of them.
This is called undefined behaviour in PHP. Most instances of it have been eradicated in PHP 8, but prior to that version when you passed a wrong parameter to a built-in function, that function would usually throw a warning and return null (or false).
There were a lot of circumstances when no warning was produced at all! This behaviour was not documented on each page as this would be a mess and by definition "undefined behaviour" has no defined behaviour.
This means that code like the following would throw no warning and simply return null:
// V - string passed instead of a numerical value
var_dump(mysqli_query($mysqli, 'SELECT 1', 'foo'));
PHP was very forgiving with parameter types and when you passed the wrong type, it tried to convert it into the proper type, but when this was not possible then PHP had no defined behaviour of what should happen. Thankfully, this has been fixed in 99% of cases in PHP 8.0.

PHP 7.2 strange in_array behaviour

I upgraded from php 5 to 7.2, and there is no problem at local (some changes needed, but it solved).
One of my function not working in production server.
The code looks like this:
$someBool = in_array($some, array("asd", "fgh", "etc"));
If I make a var_dump on this, the result is UNKNOWN:0, but if I make a vardump exactly below this (there is no any if station before dump), the function works correctly, end the dump result will be bool (true) or bool (false).
(I don't overwrite this variable)
Again if I comment the var_dump line, the function works incorrectly.
There is anybody who has idea what can cause this behaviour?
Thanks for your help.
In the original function:
$needCmdText = in_array($fieldName,array(
'cmdpreid','cmdpostid','cmdskipid',
'cmdfixid','cmdexpid','cmdsysid'
));
Where the $fieldName always 'cmdexpid' from the client. (at my test cases)
And a funny news, a simple echo solve the problem too, but it should be under this.
I changed the php 7.2 to 7.1, which solved the problem without any code changing. (No need to dump, to solve).
I think there is a strange bug in php 7.2, which doesn't occure in windows environment.

PHP Post_method hacking

I ran into the snippet online
https://www.quora.com/Why-is-PHP-hated-by-so-many-developers
when I was doing some research about PHP, and I simply have no idea how the codes work.
Can anyone kindly explain what happens in the snippet and how one can log in without knowing the password?? or just give me some relevant articles to read. Thanks in advance.
See the manual:
Returns ... 0 if they [strings] are equal.
So, by the snippet logic, you should compare 0 to 0 in the end. But when you send password[]=wrong, you actually send an array, forcing strcmp to throw a warning, completely bypassing the function call and perceive the condition as true
You should always use strict comparison, just in case. So in the snippet above it would be enough to compare strictly by type and value (with ===):
if(strcmp($POST['password'], "sekret") === 0)
In this case password[]=wrong would not work anymore.

json_decode thinks a normal string is valid

Seems my old server this would return NULL or false...the new server returns the value, weird.
var_dump(json_decode("this is a normal string, not JSON"));
Output:
string(33) "this is a normal string, not JSON"
Expected:
NULL
You have not really formulated a question, but I try to answer it anyway:
Every software contains bugs. That's normal. We share the code, we share the bugs. What you ask about is a reported and fixed software flaw in PHP. Upgrade your PHP version or live with the bug.

PHP validation booleans using filter_var

I'm using filter_var to validate boolean values but I did not expect it to not recognize FALSE. Why does this happen?
filter_var(FALSE, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)
returns
null
filter_var is new as of PHP 5.2. You've run into a known bug: https://bugs.php.net/bug.php?id=49510
Feel free to vote on or comment on that bug.
You're trying to do something like this:
$v = filter_var($v, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)
There are a number of cheap workarounds like this:
$v = $v===FALSE ? FALSE : filter_var($v, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)
It sounds like this is actually how it's supposed to work, strangely enough (yes, my mind was blown by that). From https://bugs.php.net/bug.php?id=51344
This is going to sound insane when you've looked at the underlying
filter code, but this is actually correct according to the
documentation: the default behaviour of filter_input() is to return
NULL for non-existent inputs and false when validation fails, and
FILTER_NULL_ON_FAILURE simply flips that behaviour to false for
non-existent inputs and NULL on validation failure. (No, I don't have
a clue where that would be useful either, and the name of the flag is
unfortunate in the filter_input() context, since it implies that NULL
wouldn't normally be returned. It makes more sense when used with
filter_var(), which doesn't have the non-existent input case.)
[table omitted due to SO formatting]
I'll pop a comment into the filter_input() and filter_input_array()
implementations to note that this is by design, even though the code
does kind of look wrong.
Closing Won't Fix.
This was the behaviour when filter_var was first introduced with version 5.2 and resolved at some point after 5.4 as is seen by this https://3v4l.org/Cv1MZ
Starting from version 5.4 this is what happens:
var_dump(filter_var(FALSE, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
bool(false)
which makes much more sense.
According to the documentation
Returns true for "1", "true", "on" and "yes". Returns false otherwise.
Anything different than the values mentioned above is considered falsy. This is not to test if a variable is actually a boolean like with typeof or is_bool(), but more like a mean to test if the input comming from the user (usually an <input type="checkbox"> form) is truthy/falsy.
The behavior of this function could be understand as let it go through if it's correct rather than a mean to test the type of a variable (we have lots of other functions for this). Exemple :
filter_var('435345', FILTER_VALIDATE_INT)
The type is a string, but the result is not true/false as the intention is not to validate the type. So an int would be returned (let go through).

Categories