Can anyone tell me, if there is an error in the following code, please?
eval ("\$typeselectbit = \"".$cmstpl->get("admin_selectbitdefault")."\";");
$result = $cmsdb->query("SELECT * FROM cms".$n."_type WHERE deleted = '0' ORDER BY typename ASC");
while ($type = $cmsdb->fetch_array($result))
{
$typeid = $type['typeid'];
$typename = $type['typename'];
eval("\$typeselectbit .= \"".$cmstpl->get(ifelse($GPC['typeid'] == $typeid, "typeselectbit2", "typeselectbit"))."\";");
}
It doesn't output the first entry from the array. But maybe the error is somewhere else.
At the moment, I'm not sure, where this problem is coming from.
What do you think? Does it look correct to you?
And if not, what do I have to fix and how exactly should it look like?
Or do I have to look somewhere else in the script?
Any specific hints, which could help to find the reason?
Thank you for your help! :)
The last line in your code eval("\$typeselectbit .= \"".$cmstpl->get(ifelse($GPC['typeid'] == $typeid, "typeselectbit2", "typeselectbit"))."\";"); has a parse error. ifelse is not valid PHP syntax (unless that is a function you have declared previously). It could also be any other number of errors occurring inside of the eval construct.
According to the manual
If there is a parse error in the evaluated code, eval() returns FALSE and execution of the following code continues normally. It is not possible to catch a parse error in eval() using set_error_handler().
It's not clear why you chose to use eval at all here, but one of the down sides, among others, is that you typically can't easily debug these kinds of errors inside of eval. If you ran this code outside of eval you'd immediately see the parse error.
Related
I've just read the page on Expressions in the PHP docs, and right at the top it says:
The simplest yet most accurate way to define an expression is "anything that has a value".
That simple definition includes all functions and most language constructs, however there a few language constructs that explicitly state they do not return a value.
Here is a list of language constructs that do return a value:
empty
eval
include
include_once
isset
list
require
require_once
print
Here are the interesting few which do not return a value, and therefore are not expressions:
die
echo
exit
return
unset
__halt_compiler
I find die and exit of particular interest, because they can be used as expressions in PHP despite having no return values. The following lines of code all throw a syntax error, as expected:
echo 'Hi' or echo 'Bye';
if(echo('foo'))
return return(1);
$foo['bar'] = isset($foo['bar']) ? unset($foo['bar']) : 0;
if(unset($foo['bar']))
__halt_compiler() or die;
However the following PHP code is completely free of syntax errors:
print 'Hi' or print 'Bye'; // Makes sense, print returns a value
if(!die() and exit) // Wait what's happening here?
quit(die(exit(quit()))); // die and exit don't have return values (does quit?)
$x = true ? die/2 : 5*exit();
$y = pow(die,7);
isset($_GET['bar']) or die(); // This one is actually pretty commonly used.
function quit(){
return exit;
}
I've looked through the PHP docs and can't find any mention of this special treatment of die() and exit(). Do any PHP experts know if this is documented anywhere. Is this intended behaviour, and is the isset($_GET['bar']) or die(); pattern safe to use; could it suddenly break in a future version of PHP?
PHP does not detect errors except at run time when the code path is reached. Unlike many other languages, it does not list the errors when the page is "compiled" - so you'll only see errors as their respective lines of source code are executed.
In your example, the evaluation of the return value of exit or die is never done. PHP doesn't report an error because it never tried to evaluate the result in the first place, because the thread exited.
die and exit (they share the T_EXIT token) fall under the rules for expr_without_variable during the parsing phase, which is why PHP is happy to have them in an expression context without giving a syntax error.
Do any PHP experts know if this is documented anywhere.
There is no description of the special treatment in the PHP manual, however the first example on the exit manual page shows it being used as … or exit.
Is this intended behaviour, and is the isset($_GET['bar']) or die(); pattern safe to use; could it suddenly break in a future version of PHP?
Yes. Yes. Anything's possible, however unlikely.
A wild guess is that die and exit do return a value, however, it will never be returned since the execution is halted before it is returned.
This might have been implemented in order to add some "usefulness" to the die and exit functions.
die and exit return value, however that value have to be used by the program that has called the PHP script. This comment describes the behavior.
We have an old version of CakePHP that we've moved to a new server running PHP 5.6 and we've started to recieve this error when adding a product to the basket:
Warning (2): Illegal string offset 'AddBasketData'
[APP/controllers/personalisation_controller.php, line 848]
Here is line 848 within the file:
if (is_array($this->data['AddBasketData'])) {
$personalisation_data['Personalise'] = $this->data['AddBasketData'];
}else {
$personalisation_data['Personalise'] = array();
}
Could anyone shed any light on this, I think it's down to the specific PHP version we're running now but any help would be great.
Thanks
Transforming my comments into an answer :
The problem here seems to be that $this->data is a string and not an array.
You should test this first, then check if the offset AddBasketData exists, and finally if the offset AddBasketData is an array :
if (is_array($this->data) && isset($this->data['AddBasketData']) && is_array($this->data['AddBasketData'])) {
$personalisation_data['Personalise'] = $this->data['AddBasketData'];
} else {
$personalisation_data['Personalise'] = array();
}
Of course, that will only correct the symptoms (which is the raised warning), you might have some code debugging to do to find out why $this->data is a string instead of an array.
As noted by #roberto06 in the comments to your question, the reason you're getting the error is because you're trying to treat a string value as an array.
The reason for that specific error message is because you can use the array-offset notation to fetch a single character from the string. Just like you'd do in C's string arrays. But this only support numerical indices, and not a string index as shown in the code you posted.
Now, the easy way to stop the error from occurring is to simply test the type of the data, and whether or not the given index actually exists.Like so:
if (is_array ($this->data) && !empty ($this->data['AddBasketData'])) {
$personalisation_data['Personalise'] = $this->data['AddBasketData'];
} else {
$personalisation_data['Personalise'] = array();
}
However, seeing as you're not suddenly getting this error after update hints towards something else being the issue. Especially since the code you posted expects the value stored in the Personalise index to be an array. I'd trace where the $this->data member gets set, and changed, to see if you can find the underlying reason for why this apparent change in behavior. This might be the side-effect of a more nefarious subtle bug, after all.
What is wrong with this code? I am trying to return an array and use it in the caller function.
function my_subjects()
{
$all_my_teams=my_teams();
$k=0;
$_subjects=array();
while($team=mysql_fetch_assoc($all_my_teams))
{
$q="SELECT $this->user_field FROM $team";
$r=mysql_query($q);
while($i=mysql_fetch_assoc($r))
{
$_subjects[k++]=$i;
}
}
return $_subjects;
}
Note: the function my_teams() returns the value similar to the $r variable which is used through all_my_teams variable. it contains all the names of teams.
Turn up error_reporting to see if your code is generating errors.
Check if your query is successful if( ! $r=mysql_query($q) ) { die(mysql_error()); }
var_dump($_subjects); to see if the data is what you expect it to be.
Maybe actually tell us what's going wrong? You've just posted a block of code and told us "it doesn't work." which isn't terribly indicative of a problem.
$k is irrelevant, just use $_subjects[]=$i;. [wouldn't cause an error, just easier]
Stop using mysql_* functions and port your code to PDO or MySQLi to:
Benefit from parameterized queries which can help protect against SQL injection.
Stop everyone on SO starting an unrelated argument in the comments about it.
while($i=mysql_fetch_assoc($r))
{
$_subjects[k++]=$i;
}
Here you also have to provide a field name for $i. Something like
while($i=mysql_fetch_assoc($r))
{
$_subjects[$k++]=$i["field_name"];
}
Array returning part is just fine.
Edit: Your variable k was missing a $ sign as well.
$_subjects[$k++] = $i;
should be fine, since you're using mysql_fetch_assoc() $i will contain an associative array of the result set.
If this is returning an empty array (is that the correct problem?), you should double check that your sql is correct and actually returning data/data that you expect.
Edit: Like Hanky Panky mentioned, 'k' is missing a $ sign in your code - that is likely to be your problem - PHP should be throwing a parse error for that one, so make sure you have error_reporting() enabled.
What I have and want to do
I have an input area.
I have a JS script what reads the input area's innerHTML and encodes it using encodeURICompontent then sends the value to evaluate.php?code=+value;
I have an evaluate.php what GET's the code's value from the URL and returns an evaluated value using eval($code) to the javascript.
And at the end it puts the xmlHttp.responseText to a div.
But I get this error when the eval is executed:
Parse error: syntax error, unexpected '"', expecting T_STRING in /Applications/MAMP/htdocs/Apps/editor/includes/exe.php(5) : eval()'d code on line 1
Evaluate.php
if(isset($_GET["code"])){
$e = $_GET["code"];
echo eval($e);
}
The value what I try to evaluate is just:
echo "Hello World!";
Then this is looks like in $_GET["code"] as:
echo \"Hello World!\";
According to PHP's documentation:
eval() returns NULL unless return is
called in the evaluated code, in which
case the value passed to return is
returned. If there is a parse error in
the evaluated code, eval() returns
FALSE and execution of the following
code continues normally. It is not
possible to catch a parse error in
eval() using set_error_handler().
So I think there may be a problem when you run echo eval($e).
P.S. It's best practice not to use double quotes in PHP unless a variable is contained within those quotes. For example, use "Hello, $name" and use 'Hello, Bob'.
Obviously you have an error in a string you are tying to evaluate. Try to output it first and see if it has semi columns and things like that.
But you should never (!) evaluate code you get from URL! Never-never, anyone can send "exec('rm -rf /')".
I feel terrible answering this. In your PHP settings, magic_quotes_gpc might be enabled which "corrupts" your incoming data by escaping it.
In order to get it working, you might want to add a little more insecurity to your undertaking by disabling magic quotes.
If that doesn't fix it, debug your input by following Silver Light's suggestions.
I found this line of code in the Virtuemart plugin for Joomla on line 2136 in administrator/components/com_virtuemart/classes/ps_product.php
eval ("\$text_including_tax = \"$text_including_tax\";");
Scrap my previous answer.
The reason this eval() is here is shown in the php eval docs
This is what's happening:
$text_including_tax = '$tax ...';
...
$tax = 10;
...
eval ("\$text_including_tax = \"$text_including_tax\";");
At the end of this $text_including_tax is equal to:
"10 ..."
The single quotes prevents $tax being included in the original definition of the string. By using eval() it forces it to re-evaluate the string and include the value for $tax in the string.
I'm not a fan of this particular method, but it is correct. An alternative could be to use sprintf()
This code seems to be a bad way of forcing $text_including_tax to be a string.
The reason it is bad is because if $text_including_tax can contain data entered by a user it is possible for them to execute arbitrary code.
For example if $text_include_tax was set to equal:
"\"; readfile('/etc/passwd'); $_dummy = \"";
The eval would become:
eval("$text_include_tax = \"\"; readfile('/etc/passwd'); $_dummy =\"\";");
Giving the malicious user a dump of the passwd file.
A more correct method for doing this would be to cast the variable to string:
$text_include_tax = (string) $text_include_tax;
or even just:
$text_include_tax = "$text_include_tax";
If the data $text_include_tax is only an internal variable or contains already validated content there isn't a security risk. But it's still a bad way to convert a variable to a string because there are more obvious and safer ways to do it.
I'm guessing that it's a funky way of forcing $text_including_tax to be a string and not a number.
Perhaps it's an attempt to cast the variable as a string? Just a guess.
You will need the eval to get the tax rate into the output. Just moved this to a new server and for some reason this line caused a server error. As a quick fix, I changed it to:
//eval ("\$text_including_tax = \"$text_including_tax\";");
$text_including_tax = str_replace('$tax', $tax, $text_including_tax);
It is evaluating the string as PHP code.
But it seems to be making a variable equal itself? Weird.
As others have pointed out, it's code written by someone who doesn't know what on earth they're doing.
I also had a quick browse of the code to find a total lack of text escaping when putting HTML/URIs/etc. together. There are probably many injection holes to be found here in addition to the eval issues, if you can be bothered to audit it properly.
I would not want this code running on my server.
I've looked through that codebase before. It's some of the worst PHP I have seen.
I imagine you'd do that kind of thing to cover up mistakes you made somewhere else.
No, it's doing this:
Say $text_including_tax = "flat". This code evaluates the line:
$flat = "flat";
It isn't necessarily good, but I did use a technique like this once to suck all the MySQL variables in an array like this:
while ($row = mysql_fetch_assoc($result)) {
$var = $row["Variable_name"];
$$var = $row["Value"];
}