The following code is working perfectly:
${0x0} = 'test';
echo ${0x0}; // prints "test"
But I can't figure out why. 0x0 (or 0, as non-hex people call it) is a random container, it could have been any number, but php variables can't start with a number. What's so special about the { } used here, and what are their limitations ?
First of all, 0x0 is just a regular 0 in hexadecimal representation that gets cast to string '0' when used with the variable variable syntax:
var_dump(0x0===0); // prints "bool(true)"
${0x0} = 'test';
echo ${0x0}; // prints "test"
echo ${'0'}; // prints "test" as well
var_dump(get_defined_vars()); // contains ["0"] => string(4) "test"
You're correct whey you say that it isn't a valid variable name:
Variable names follow the same rules as other labels in PHP. A valid
variable name starts with a letter or underscore, followed by any
number of letters, numbers, or underscores. As a regular expression,
it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
This is the reason why $0foo = 'Test'; triggers a parse error.
Some quick testing with the variable variables syntax reveals that, in fact, PHP does not seem to really care about variable names as far as they are strings:
${'123 abc xyz '} = 'Test';
echo ${'123 abc xyz '}; // Test
echo ${'123 abc xyz '}; // PHP Notice: Undefined variable: 123 abc xyz in ...
var_dump(get_defined_vars()); // ["123 abc xyz "] => string(4) "Test"
My guess is that the aforementioned naming restriction is imposed by the source code parser rather than the language core. It needs such rules to tell variables apart when analysing PHP code. Internally, the Zend engine that powers PHP handles variables as a hash map:
PHP variables, in general, consist out of two things: The label, which
might, for instance, be an entry in a symbol table, and the actual
variable container.
So as far as it receives a valid string for the label, it's happy.
From the documentation:
Curly braces may also be used, to clearly delimit the property name. They are most useful when accessing values within a property that contains an array, when the property name is made of mulitple parts, or when the property name contains characters that are not otherwise valid (e.g. from json_decode() or SimpleXML).
To me this implies that if you use ${...}, there are no limitations regarding what characters may be used in a variable name. Whether you should however...
PHP parser provides a special syntax to create a variable name from any expression that returns string (or can be casted to string), eg.:
<?php
define('A', 'aaa');
${' _ '} = 'blah';
${'test' . A . (2 + 6)} = 'var';
echo ${' _ '}; // blah
echo ${'testaaa8'}; // var
${'123'} = 'blah';
echo ${100 + 23}; // blah
function returnVarName() {
return 'myVar';
}
$myVar = 12;
echo ${returnVarName()}; // 12
This syntax is also available for object properties:
$object->{' some property ... with strage name'};
0x0 is just a hex representation of 0 literal.
In other words everything within the curly braces in such cases is a string!
So s0x0 is indeed the hex version of 0 but here both are strings! That is why ${0x0} or ${0} work, where $0 or $0x0 won't!
On top of what #Michael Robinson said, in your example this will also be valid:
${0x0} = 'test';
$var = "0";
echo $$var; // prints "test"
Related
When we check:
dir1/dir2/../file.txt ==== this is same as =====> dir1/file.txt
I am interested is something same thing available in PHP, like:
$name= "Hello ". $variable . "World";
if i had $variable = "../Hi" (or anything like that) so, it removed (like backslashing) the previous part, printed Hi World ?
(p.s. I dont control the php file, I ask about how attackers can achieve that).
(p.s.2. I dont have words to downvoters for closing this. I think you have problems with analysing of questions before you close).
In PHP there exist no special ../ (or any other string) that when concatenated to another string generates any string other than the combine original string concatenated with the new string. Concatenation, regardless of content of strings always results in:
"<String1><String2>" = "<String1>"."<String2>";
Nothing will not 'erase' prior tokens in a string or anything like that and is completely harmless.
Caveat!!!! Of course if the string is being used somewhere that interprets it in some specific way where any character or group of characters in the ../ is treated special such as:
In a string used for regex pattern
In a string used as a file path (in that case, when it's evaluated it will do exactly what you'd expect if you'd typed it.
A string used in a SQL query without properly escaping (as with binding params/values via prepared statements)
etc...
Now, if you want to remove the word prior to each occurence of ../ starting a word in a sentence, sort-of replicating how the .. in a path means, go up one level (in effect undoing the step made to the directory in the path prior to it).
Here's a basic algorithm to start you out (if you are able to change the source code) :
Use explode with delimiter " " on the string.
Create a new array
Iterate the returned array, if not ../ insert at end of new array
if entry starts with ../, remove the end element of the 2nd array
insert the the ../somestring with the ../ string replaced with empty string "" on the end of the 2nd array
Once at end of array (all strings processed), implode() with delimiter " "
Here's an example:
<?php
$variable = "../Hi";
$string = "Hello ". $variable . " World"; // Note: I added a space prior to the W
$arr = array();
foreach(explode(" ", $string) as $word) {
if (substr( $word, 0, 3 ) === "../") {
if(!empty($arr)){
array_pop($arr);
}
$arr[] = str_replace("../", "", $word);
} else {
$arr[] = $word;
}
}
echo implode(" ", $arr);
I have files with texts an constants. How can I get constant name and constant value. Problem is that constant value has sometime spaces. I read files with file() and then with foreach...
Example:
define('LNG_UTF-8', 'Universal Alphabet (UTF-8)');
define('LNG_ISO-8859-1', 'Western Alphabet (ISO-8859-1)');
define('LNG_CustomFieldsName', 'Custom Field');
define('LNG_CustomFieldsType', 'Type');
I already tried:
to get constant name:
$getConstant1 = strpos($mainFileArray[$i], '(\'');
$getConstant2 = strpos($mainFileArray[$i], '\',');
$const = substr($mainFileArray[$i], $getConstant1 + 2, $getConstant2 - $getConstant1 - 2);
to get constant value
$position1 = strpos($file[$i], '\',');
$position2 = strpos($file[$i], '\');');
$rest = substr($file[$i], $position1 + 3, $position2 - $position1 - 2);
but not working when is space or ','...
How can i make this always working??
A regular expression matching this would be this:
preg_match("/define\(\s*'([^']*)'\s*,\s*'([^']*)'\s*\)/i", $line, $match);
echo $match[1], $match[2];
See http://rubular.com/r/m9plE2qQeT.
However, that only works if the strings are single quoted ', don't contain escaped quotes, the strings are not concatenated etc. For example, this would break:
define('LNG_UTF-8', "Universal Alphabet (UTF-8)");
define('LNG_UTF-8', 'Universal \'Alphabet\' (UTF-8)');
define('LNG_UTF-8', 'Universal Alphabet ' . '(UTF-8)');
// and many similar
To make at least the first two work, you should use token_get_all to parse the PHP file according to PHP parsing rules, then go through the resulting tokens and extract the values you need.
To make all cases work, you need to actually evaluate the PHP code, i.e. include the file and then simply access the constants as constants in PHP.
You should use get_defined_constants() function for that. It returns an associative array with the names of all the constants and their values.
Are these 2 two "spellings" equivalent? Just wondering.
${var} out of context could be either correct or not. If it is used inside of the string like "foo ${var} bar" - then it is the same.
If it is used right in the code - then ${var} is incorrect, and ${'var'} should be used instead.
The valid cases for using ${...} are:
Inside the string in cases like "ab${cd}e" - when all the letters go without spaces, "${a['b']}" - when you use it with arrays
When you want to assemble the variable name dynamically: ${'a_' . $i}
Pretty much. The only difference is that you can enter code to be parsed in between the curly braces to get "variable" variable names.
Ex.
${'t'.'e'.'s'.'t'} = 'test'; // is the same as $test = 'test';
${substr('testaaa',0,4)} = 'test'; // the same
You can even do something like:
${ 'a' == 'b' ? 'Foo' : 'test' } = 'test'; //the same
It is essentially the same as:
$var_name = substr('testaaa',0,4);
$$var_name = 'test';
I would like to know when and why should I use {$var}
echo "This is a test using {$var}";
and when (and why) should I use the simple form $var
echo "This is a test using $var";
You would use the latter when a) not accessing an object or array for the value, and b) no characters follow the variable name that could possibly be interpreted as part of it.
http://php.net/manual/en/language.variables.variable.php
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.
The brackets allow you to remove ambiguity for the PHP parser in some special cases.
In your case, they are equivalent.
But consider this one:
$foobar = 'hello';
$foo = 'foo';
echo "${$foo . 'bar'}"; // hello
Without the brackets, you will not get the expected result:
echo "$$foo . 'bar'"; // $foo . 'bar'
For clarity purposes, I would however strongly advise against this syntax.
If you write
echo "This is a test using $vars"
You do not get content of $var in result text.
If you write
echo "This is a test using {$var}s";
Everything will be OK.
P.S. It works only with "" but not for ''.
The {} notation is also useful for embedding multi-dimensional arrays in strings.
e.g.
$array[1][2] = "square";
$text = "This $array[1][2] has two dimensions";
will be parsed as
$text = "This " . $array[1] . "[2] has two dimensions";
and you'll end up with the text
This Array[2] has two dimensions
But if you do
$text = "This {$array[1][2]} has two dimensions";
you end up with the expected
This square has two dimensions.
I'm running PHP 5.3.0. I've found that the curly string syntax only works when the first character of the expression is $. Is there a way to include other types of expressions (function calls, etc)?
Trivial example:
<?php
$x = '05';
echo "{$x}"; // works as expected
echo "{intval($x)}"; // hoped for "5", got "{intval(05)}"
<?php
$x = '05';
echo "{$x}";
$a = 'intval';
echo "{$a($x)}";
?>
No. Only variables of various forms can be substituted using variable substitution.
take a look at this link LINK
Example of the code,
Similarly, you can also have an array index or an object property parsed. With array indices, the closing square bracket (]) marks the end of the index. For object properties the same rules apply as to simple variables, though with object properties there doesn't exist a trick like the one with variables.
<?php
// These examples are specific to using arrays inside of strings.
// When outside of a string, always quote your array string keys
// and do not use {braces} when outside of strings either.
// Let's show all errors
error_reporting(E_ALL);
$fruits = array('strawberry' => 'red', 'banana' => 'yellow');
// Works but note that this works differently outside string-quotes
echo "A banana is $fruits[banana].";
// Works
echo "A banana is {$fruits['banana']}.";
// Works but PHP looks for a constant named banana first
// as described below.
echo "A banana is {$fruits[banana]}.";
// Won't work, use braces. This results in a parse error.
echo "A banana is $fruits['banana'].";
// Works
echo "A banana is " . $fruits['banana'] . ".";
// Works
echo "This square is $square->width meters broad.";
// Won't work. For a solution, see the complex syntax.
echo "This square is $square->width00 centimeters broad.";
?>
there are different things you can achieve with the curly brace, but it is limited, depending on how you use it.
<?php
class Foo
{
public function __construct() {
$this->{chr(8)} = "Hello World!";
}
}
var_dump(new Foo());
Generally you don't need the braces around variables, unless you need to force PHP to treat something as a variable, where its normal parsing rules otherwise might not. The big one is multidimensional arrays. PHP's parser is non-greedy for deciding what's a variable and what isn't, so the braces are necessary to force PHP to see the rest of the array element references:
<?php
$arr = array(
'a' => array(
'b' => 'c'
),
);
print("$arr[a][b]"); // outputs: Array[b]
print("{$arr[a][b]}"); // outputs: (nothing), there's no constants 'a' or 'b' defined
print("{$arr['a']['b']}"); // ouputs: c