0

I am trying to override some variables in my PHP file using variable variables, but I am getting unexpected results, where the original value is never overwritten, but where the new variable-variable value has a unique value from that of its original variable counterpart.

$case1 = (time() > strtotime('11/22/2020 07:00:00:000AM'));
$case2 = (time() > strtotime('11/16/2020 07:00:00:000AM'));
$case3 = (time() > strtotime('12/01/2020 12:00:00:000PM'));
$case4 = (time() > strtotime('04/24/2021 05:00:00:000AM'));
if (!empty($_GET['schedule_test'])) { $$_GET['schedule_test'] = true; }

If someone someone visits the page path /?schedule_test=case4, the above line should overwrite the variable $case4, because $_GET['schedule_test'] would equal case4 making the statement $$_GET['schedule_test'] = true the equivalent of $case4 = true.

However, even when visiting the URL path /?schedule_test=case4 I still get the value false for $case4. I var_dumped the values for both $case4 and $$_GET['schedule_test'], and their values are different:

echo $case4; // false
echo $$_GET['schedule_test']; // true

The desired goal is to be able to test any of these four cases for any set times with the URL parameter schedule_test being set to any of the variable names (e.g. case1, case2, case3, case4).

3
  • 1
    Whenever you start “numbering” in variable names, that is a pretty good indicator, that you should actually be using an array. And doing that, would at least take the potential danger out of what you are doing. (Imagine you had a variable like $userIsAdmin set in your code somewhere before that point, to false, because I am not an admin on your site, and now I call your script with /?schedule_test=userIsAdmin … see the problem?) Commented Apr 8, 2021 at 7:46
  • @CBroe My actual variables do have more meaningful names; I just used numbered variables to further generalize my question, but that is something good to keep in mind for future reference — thanks! Commented Apr 8, 2021 at 12:49
  • @CBroe that is also a very valid point about the risk of someone using a variable name like $is_admin. I think I'll adjust my code to use an array after all, so as to prevent overwriting any unrelated variables. Thanks again! Commented Apr 8, 2021 at 12:54

2 Answers 2

3

PHP documentation says

In order to use variable variables with arrays, you have to resolve an ambiguity problem. That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable. The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.

So, you should use

${$_GET['schedule_test']}

However, I would strongly advise against using user input directly to decide which variable to write like this. There is a very high risk of allowing attackers to change the internal behaviour of your code.

Sign up to request clarification or add additional context in comments.

1 Comment

This worked perfectly for me! Thanks for that additional context. I really appreciate the time you took to answer this thoughtfully and provide the additional warning. I'll adjust my code to, instead of using the user-input to write/overwrite a variable, use the user-input to set an array variable value and check for that to prevent any overwriting of any other variables that control the behavior of my code, as you mentioned. Thanks!
2

Since $_GET is an array, you cannot use $$ to access the value of $_GET and get the variable, this has to do with PHPs internal parser not knowing if you want to access $$_GET and then the key or $_GET the key and then the variable, this is talked about in the documentation for variable variables three paragraphs above example #1. To fix this you have to surround your $_GET with curly brackets.

if (! empty($_GET['schedule_test'])) {
    ${$_GET['schedule_test']} = true;
}

echo $case4;
echo ${$_GET['schedule_test']};

1 Comment

Thanks @Kim Hallberg! This is a great solution. I really appreciate your approach and the example you provided. Only because the answer was a bit quicker and provided an additional context of the warning, I selected the first answer by NineBerry, but your solution is great as well, and I really wish I could choose both as accepted answers. Thanks again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.