By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
426,115 Members | 898 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 426,115 IT Pros & Developers. It's quick & easy.

eval() is insecure, but what are the alternatives?

P: n/a
Hi!

I don't want to use eval() in order to parse a user-supplied formula.
What alternatives do I have? PHP has no standard functionality for
tokenizing or parsing expressions in this regard.

Here is a simple example: The user supplies the following formula in
string format,
"a = (6+10)/4",
and the script needs to find out what the value of 'a' is.

How can I go about it without using eval(), since using eval in this
case could be very risky! (The user can supply *any* expression, as
there is no function that can determine the meaning of the string as an
expression).

Thank you for taking the time t read my question.

Jan 20 '06 #1
Share this Question
Share on Google+
8 Replies


P: n/a
There are several options:
1. Check the user input to only contain number, operators and
parenthesis and then supply it to eval. This would be safer than using
eval without checking, but it may still be insecure and it is not the
right option. If you need to accept variables and functions in the
expression, making this secure becomes close to impossible.
2. You may parse the expression and compute the result using PHP code.
This is a better option, but may not be worth the time it takes to
write a parser.

I tried searching the web for a math expression parser, but I did not
found one. I have written something to get you started:
http://svn.linuxonly.nl/filedetails....calculator.php
It is not complete. It does not check parenthesis and does not give
precendence to * over + (for example). It converts the expression to
Reverse Polish notation and than computes it.

If you want to extend my file, you may find
http://en.wikipedia.org/wiki/Reverse_Polish_Notation interesting.
Please send any new version to me.

Good luck.

Jan 20 '06 #2

P: n/a
werner wrote:
I don't want to use eval() in order to parse a user-supplied formula.
What alternatives do I have? PHP has no standard functionality for
tokenizing or parsing expressions in this regard.
Other than writing your own parser (or using one already done), I don't
think you have any alternatives.
Here is a simple example: The user supplies the following formula in
string format,
"a = (6+10)/4",
and the script needs to find out what the value of 'a' is.

How can I go about it without using eval(), since using eval in this
case could be very risky! (The user can supply *any* expression, as
there is no function that can determine the meaning of the string as an
expression).


Example using an already done parser (bc):

<?php
/* needs error checking */
$formula = 'a = (6+10)/4';

/* remove the left part of assignment */
$value = trim(substr($formula, strpos($formula, '=')+1));
$value = escapeshellarg($value);

$calculated = `echo $value | bc`; /* backticks! */
echo $calculated, "\n";
?>

tmp$ php foo.php
4

"bc" is "an arbitrary precision numeric processing language"
http://www.gnu.org/software/bc/bc.html

But, even so, I wouldn't pass input from the user directly to bc without
checking/validating it first (at least not until I've read thoroughly
bc's documentation).

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Jan 20 '06 #3

P: n/a
There is bc under Unix. Although inserting user-supplied data into a
shell command might be even more dangerous.

Jan 20 '06 #4

P: n/a
Chung Leong wrote:
There is bc under Unix. Although inserting user-supplied data into a
shell command might be even more dangerous.


There's also bc for Windows:
http://gnuwin32.sourceforge.net/packages/bc.htm

And I agree that passing user data to a shell command is dangerous.
but maybe this is enough protection:

$formula = 'user data';
if preg_match('/^[-+*/^()\s0-9]+$/', $formula) {
/* do shell command with properly escaped data */
} else {
/* bad entry */
}

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Jan 20 '06 #5

P: n/a
Thanks for the input, this topic has had me wrestling with PHP for
quite some time.

Pedro Graca wrote:
$formula = 'user data';
if preg_match('/^[-+*/^()\s0-9]+$/', $formula) {
/* do shell command with properly escaped data */
} else {
/* bad entry */
}
Well, since the user should be able to supply arbitrary variables in
the expression (which will then make the whitelist filtering approach a
bit hard to accomplish, e.g. we'll need to add a "[a-z]+" in there as
well), some innocent-looking "expressions" like 'rm -rf *' might still
slip through.
I have written something to get you started:
http://svn.linuxonly.nl/filedetails....uxonly.nl&path...
It is not complete. It does not check parenthesis and does not give
precendence to * over + (for example). It converts the expression to
Reverse Polish notation and than computes it.
Thanks for the help! I agree with the parser suggestion and have also
previously searched for an expression parser, as this would be the best
approach. I just can't *believe* that there isn't one yet, considering
the complexity of classes found in Pear, Pecl and those made for
academic and educational purposes.

I am also looking at maybe porting an existing Java solution, what do
you think? It's just going to take some time, and I sadly don't have
much of that left.
There is bc under Unix. Although inserting user-supplied data into a
shell command might be even more dangerous.


That is also an interesting approach, but I do feel that I would like
to keep it a native php solution.

Funny thing, though, that there is no native parser function available,
since PHP is after all an interpreted language. Something like eval()
that could return tokens, instead of the evaluated value would be
*extremely* helpful in this regard. What do you think?

Thanks again, everyone.

Jan 20 '06 #6

P: n/a
werner wrote:
I agree with the parser suggestion and have also
previously searched for an expression parser, as this would be the best
approach.

I am also looking at maybe porting an existing Java solution, what do
you think? It's just going to take some time, and I sadly don't have
much of that left.
Use bc! :-)
There is bc under Unix. Although inserting user-supplied data into a
shell command might be even more dangerous.


My example (below) looks safe. It could be made tighter by checking for
long lines, disabling single quotes and "strange" characters (ESC, NUL,
....), and whatever else you might think of.

.... but bc is, perhaps, best discussed on gnu.utils.help.
That is also an interesting approach, but I do feel that I would like
to keep it a native php solution.

<?php
$formula = <<<FORMULA
/*
* find the hypotenuse of a right triangle
* with height = 5 and area = 25
*/

/* !!!! ATTENTION !!! */
rm -rf * ## I tried it!!
## it seems perfectly safe (???)
/* !!! ATTENTION !!! */

scale = 8 ## work with 8 decimals

/* area = h * w / 2 */
h = 5 ## height
area = 25 ## area
w = 2*area / h ## compute width

/* hypotenuse = sqrt(h*h + w*w) */
hyp = sqrt(h*h + w*w) ## compute hypotenuse
hyp ## print (and return) it
FORMULA;

$value = escapeshellarg($formula);
$calculated = `echo $value | bc`; /* backticks! */

// with "rm" in the formula, $calculated will have the error message
// from bc; it might be possible to remove all messages with a
// simple regular expression, I didn't look into that.
echo $calculated;
?>

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Jan 21 '06 #7

P: n/a
werner wrote:
Hi!

I don't want to use eval() in order to parse a user-supplied formula.
What alternatives do I have? PHP has no standard functionality for
tokenizing or parsing expressions in this regard.

<snip>

You may do sand boxing with <http://in2.php.net/runkit>

--
<?php echo 'Just another PHP saint'; ?>
Email: rrjanbiah-at-Y!com Blog: http://rajeshanbiah.blogspot.com/

Jan 21 '06 #8

P: n/a
http://muparser.sourceforge.net/
if you want to convert the code. fairly complex. better make this one a DLL
extension of PHP.

"Pedro Graca" <he****@dodgeit.com> wrote in message
news:sl*******************@ID-203069.user.individual.net...
werner wrote:
I agree with the parser suggestion and have also
previously searched for an expression parser, as this would be the best
approach.

I am also looking at maybe porting an existing Java solution, what do
you think? It's just going to take some time, and I sadly don't have
much of that left.


Use bc! :-)


http://us2.php.net/manual/en/ref.bc.php (does not have eval-like function)
instead of using backticks, use the library?

http://www.bestcode.com/html/bcparserx.html COM control that evals math,
co$t$ money.
http://www.freevbcode.com/ShowCode.asp?ID=2090 vree vb parser, not too
complicated. I am converting it now. here.

<?php
//Attribute VB_Name = "Module1"
/*
' Acclaimer and Disclaimer!
'************************************************* ********************************************
'* This code is written by Jonathan Adamit (c) 20th in December
2000. *
'* I Am in no way responsible for anything that occures as a result of
implementing *
'* this code or by using it in any way.
*
'* This code is given to you for free to do whatever you want to do with
it. *
'* My only request is that if you use it - you give me the credit for it.
*
'* I will also be very greatful if you E-mail me any improvements or
changes you made to it.*
'* Any comments or changes are to be sent to:
ad****@bgumail.bgu.ac.il *
'************************************************* ********************************************
version 1.0

'
' Example of use and remarks!
'************************************************* ************************************************** **************
'* On Error Resume Next
*
'* Dim X As Double
*
'* X = Parse("2+3*4^2*2*cos[3]+2")
*
'* if Err.Number = 11 Then MsgBox "Division by Zero", , "Uncalculatable"
*
'* if Err.Number = vbObjectError + 555 Then MsgBox "Specified Text Sequence
Not Allowed!", , "Invalid Equation" *
'*---------------------------------------------------------------------------------------------------------------*
'* cos/sin/tan/atn must be enclosed with [] as the example shows.
*
'* Use of absolute signs (|) is allowed.
*
'************************************************* ************************************************** **************
*/

function RemSpaces($Exp) {
return str_replace(" ","",$Exp);
}

function RemPlusMinus($Exp) {
$NewExp="";
$RPM = $Exp;
$Place = strpos($Exp, "+-");
if ($Place === false) { } else {
$NewExp = substr($Exp, 0, ($Place - 1)+1) . "-" . substr($Exp, -1,
(strlen($Exp) - $Place - 1)+1);
if (strpos($NewExp, "+-") === false) { } else {
$NewExp = RemPlusMinus($NewExp);
}
$RPM = $NewExp;
}
$Place = strpos($NewExp, "--");
if ($Place === false) { } else {
$NewExp = substr($NewExp, 0, ($Place - 1)+1) . "+" . substr($NewExp, -1,
(strlen($NewExp) - $Place - 1)+1);
if (strpos($NewExp, "--") === false) { } else {
$NewExp = RemPlusMinus($NewExp);
}
return $NewExp;
}
return $RPM;
}

function isnumeric($x) {
return 1==preg_match("/[\deE\.]/", $x);
}

function IsValid($Exp) {
for ($X = 0; $X < strlen($Exp); $X++) {
switch ($Exp{$X}) {
case "[": case "]": case "(": case ")": case "*": case "/": case "+": case
"-": case "^":
break;
case "|":
if (substr($Exp, $X, 2) == "||") {
echo "mdlParse: Specified Text Sequence Not Allowed";
return false;
}
break;
default:
switch(isnumeric($Exp{$X})) {
case false:
switch($X) {
case 0://1:
$Temp = substr($Exp, $X, 3);
if (($Temp != "tan") && ($Temp != "cos") && ($Temp != "sin") && ($Temp
!= "atn")) {
echo "mdlParse: Specified Text Sequence Not Allowed";
return false;
}
break;
case 1://2:
$Temp = substr($Exp, $X - 1, 3);
if (($Temp != "tan") && ($Temp != "cos") && ($Temp != "sin") && ($Temp
!= "atn")) {
echo "mdlParse: Specified Text Sequence Not Allowed";
return false;
}
break;
default://case Is > 2
$Temp = substr($Exp, $X - 2, 6);
if ((strpos($Temp, "cos[") === false) && (strpos($Temp, "sin[") ===
false) && (strpos($Temp, "tan[") === false) && (strpos($Temp, "atn[") ===
false)) {
echo "mdlParse: Specified Text Sequence Not Allowed";
return false;
}
break;
}
break;
case true:
$Temp = substr($Exp, $X, 2);
//if ((strpos($Temp, "[") >= 0) || (strpos($Temp, "(") >= 0) ||
(strpos($Temp, "s") >= 0) || (strpos($Temp, "c") >= 0) || (strpos($Temp,
"t") >= 0) || (strpos($Temp, "a") >= 0)) {
if ((strpos($Temp, "[") === false) && (strpos($Temp, "(") === false) &&
(strpos($Temp, "s") === false) && (strpos($Temp, "c") === false) &&
(strpos($Temp, "t") === false) && (strpos($Temp, "a") === false)) { } else {
echo "mdlParse: Specified Text Sequence Not Allowed";
return false;
}
break;
} //end switch $X
//Ok:
} //end switch $Exp{$X}
} //end for
return true;
}

function Mul($Exp) {
//Dim Place As Integer //'Where the sign is found
//Dim X As Integer //'Travel backward and forward on the string
//Dim Y As Integer //'Counter
//Dim Before As String //'What number goes before the sign
//Dim After As String //'What number goes after the sign
//Dim NewExp As String
//Dim BeforeStr As String //'Used to save the text that goes before our
calculation
$Exp = RemPlusMinus($Exp); //'Make sure previous calculation didn't leave
+- or --
$M = $Exp; //'Incase there's nothing to do, make sure the
function returns correct information
$Place = strpos($Exp, "*");
if ($Place === false) { } else {
$Y = 0;
$X = $Place;
do {//'loop backwards on the string to find out the number before the sign
$Y++;
$X--;
if ($X < 0) break; //'incase we got to the start of the string
if (($Exp{$X} != "+") && ($Exp{$X} != "-" || $Y == 1) && ($Exp{$X} !=
"/")) {
$Before = substr($Exp, $X, $Y);
}
} while (!(($Exp{$X} == "+") || ($Exp{$X} == "-" && $Y != 1) || ($Exp{$X}
== "/"))); //'As Long as we didn't get to the start or to another sign -
continue traveling backwards.
$BeforeStr = substr($Exp, 0, $X+1);
$Y = 0;
$X = $Place;
do {
$Y++;
$X++;
if (($Exp{$X} != "+") && ($Exp{$X} != "-" || $Y == 1) && ($Exp{$X} !=
"*") && ($Exp{$X} != "/")) {
$After = substr($Exp, $Place + 1, $Y+1); //+1 or -1? I think it's +1.
}
} while (!(($Exp{$X} == "+") || ($Exp{$X} == "-" && $Y != 1) || ($Exp{$X}
== "*") || ($Exp{$X} == "/") || ($X >= strlen($Exp)-1))); //'As long as we
didn't get to the end or to another sign - continue traveling forward.
$NewExp = $BeforeStr . ((double)$Before * (double)$After) . substr($Exp,
$X+1);
if (strpos($NewExp, "*") === false) { } else {
$NewExp = Mul($NewExp); //'Recurse incase there are *'s left
}
return $NewExp;
} //end if
return $M;
}

function Add($Exp) {
$Exp = RemPlusMinus($Exp);
$A = $Exp;
$Place = strpos($Exp, "+");
if ($Place === false) { } else {
$Y = 0;
$X = $Place;
do { //'loop backwards on the string to find out the number before the
sign
$Y++;
$X--;
if ($X < 0) break; //'incase we got to the start of the string
if (($Exp{$X} != "-" || $X == 0) && ($Exp{$X} != "*") && ($Exp{$X} !=
"/")) {
$Before = substr($Exp, $X, $Y);
}
} while (!(($Exp{$X} == "*") Or ($Exp{$X} == "-" && $X != 0) || ($Exp{$X}
== "/")));
$BeforeStr = substr($Exp, 0, $X+1);
$Y = 0;
$X = $Place;
do {
$Y++;
$X++;
if (($Exp{$X} != "+") && ($Exp{$X} != "-") && ($Exp{$X} != "*") &&
($Exp{$X} != "/")) {
$After = substr($Exp, $Place + 1, $Y);
}
} while (($Exp{$X} != "+") && ($Exp{$X} != "-") && ($Exp{$X} != "*") &&
($Exp{$X} != "/") && ($X < strlen($Exp)-1));
$NewExp = $BeforeStr . ((double)$Before + (double)$After) . substr($Exp,
$X+1);
if (strpos($NewExp, "+") === false) { } else {
$NewExp = Add($NewExp); //'Recurse incase there are +'s left
}
return $NewExp;
} //end if
return $A;
}

function Subt($Exp) {
$Exp = RemPlusMinus($Exp);
$S = $Exp;
$Place = strpos($Exp, "-");
if ($Place === 0) $Place = strpos($Exp, "-", 1);
if ($Place > 0) {
$Y = 0;
$X = $Place;
do { //'loop backwards on the string to find out the number before the
sign
$Y++;
$X--;
if ($X < 0) break; //'incase we got to the start of the string
if (($Exp{$X} != "+") && ($Exp{$X} != "*") && ($Exp{$X} != "/")) {
$Before = substr($Exp, $X, $Y);
}
} while (!(($Exp{$X} == "*") || ($Exp{$X} == "+") || ($Exp{$X} == "/")));
$BeforeStr = substr($Exp, 0, $X+1); //+1 added afterwards by Jim
$Y = 0;
$X = $Place;
do {
$Y++;
$X++;
if (($Exp{$X} != "+") && ($Exp{$X} != "-") && ($Exp{$X} != "*") &&
($Exp{$X} != "/")) {
$After = substr($Exp, $Place + 1, $Y+1);
}
} while (!(($Exp{$X} == "+") || ($Exp{$X} == "-") || ($Exp{$X} == "*") ||
($Exp{$X} = "/") || ($X >= strlen(Exp)-1)));
$NewExp = $BeforeStr . ((double)$Before - (double)$After) . substr($Exp,
$X+1);
if (strpos($NewExp, "-") === false) { } else {
$NewExp = Subt($NewExp); //'Recurse incase there are -'s left
}
return $NewExp;
}
return $S;
}

function Parentheses($Exp) {
$Exp = RemPlusMinus($Exp);
$P = $Exp;
$MiddleStr="";
$Place = strpos($Exp, ")");
if ($Place === false) { } else {
$Y = 0;
$X = $Place;
do { //'loop to find the inside of the parentheses
$Y++;
$X--;
if ($X < 0) break; //'incase we got to the start of the string
if ($Exp{$X} != "(") {
$MiddleStr = substr($Exp, $X, $Y);
}
} while ($Exp{$X} != "(");
$BeforeStr = ""; //'if it's the beginning of the string - there is nothing
before.
if ($X >= 0) $BeforeStr = substr($Exp, 0, ($X - 1)+1);
$NewExp = $BeforeStr . Parse($MiddleStr) . substr($Exp, $Place + 1);
if (strpos($Exp, ")") === false) { } else {
$NewExp = Parentheses($NewExp); //'Recurse incase there are more
parentheses
}
return $NewExp;
}
return $P;
}

function Div($Exp) {
//On Error Resume Next
$Exp = RemPlusMinus($Exp);
$D = $Exp;
$Place = strpos($Exp, "/");
if ($Place === false) { } else {
$Y = 0;
$X = $Place;
do {//'loop backwards on the string to find out the number before the sign
$Y++;
$X--;
if ($X < 0) break; //'incase we got to the start of the string
if (($Exp{$X} != "+") && ($Exp{$X} && "-" || $Y == 1) && ($Exp{$X} !=
"*")) {
$Before = substr($Exp, $X, $Y);
}
} while (!(($Exp{$X} == "+") || ($Exp{$X} == "-" && $Y != 1) || ($Exp{$X}
== "*")));
$BeforeStr = substr($Exp, 0, $X+1);
$Y = 0;
$X = $Place;
do {
$Y++;
$X++;
if (($Exp{$X} != "+") && ($Exp{$X} != "-" Or Y == 1) && ($Exp{$X} != "*")
&& ($Exp{$X} != "/")) {
$After = substr($Exp, $Place + 1, $Y+1);
}
} while (!(($Exp{$X} == "+") || ($Exp{$X} == "-" && $Y != 1) || ($Exp{$X}
== "*") || ($Exp{$X} == "/") || ($X >= strlen($Exp)-1)));
if ((double)$After==0.0) {
return "Impossible";
}
$NewExp = $BeforeStr . ((double)$Before / (double)$After) . substr($Exp,
$X+1);
if (strpos($NewExp, "/") === false) { } else {
$NewExp = Div($NewExp); //'Recurse incase there are /'s left
}
return $NewExp;
}
return $D;
}

function Power($Exp) {
$Exp = RemPlusMinus($Exp);
$P = $Exp;
$Place = strpos($Exp, "^");
if ($Place === false) { } else {
$Y = 0;
$X = $Place;
do { //'loop backwards on the string to find out the number before the
sign
$Y++;
$X--;
if ($X < 0) break; //'incase we got to the start of the string
if (($Exp{$X} != "+") && ($Exp{$X} != "-" || X == 0) && ($Exp{$X} != "*")
&& ($Exp{$X} != "/")) {
$Before = substr($Exp, $X, $Y);
}
} while (!(($Exp{$X} == "+") || ($Exp{$X} == "-" && X != 0) || ($Exp{$X}
== "*") || ($Exp{$X} == "/")));
$BeforeStr = substr($Exp, 0, $X+1);
$Y = 0;
$X = $Place;
do {
$Y++;
$X++;
if (($Exp{$X} != "+") && ($Exp{$X} != "-") && ($Exp{$X} != "*") &&
($Exp{$X} != "/")) {
$After = substr($Exp, $Place + 1, $Y+1);
}
} while (!(($Exp{$X} == "+") || ($Exp{$X} == "-") || ($Exp{$X} == "*") ||
($Exp{$X} == "/") || ($X >= strlen($Exp)-1)));
$NewExp = $BeforeStr . bcpow($Before, $After) . substr($Exp, $X+1);
if (strpos($NewExp, "^") === false) { } else {
$NewExp = Power($NewExp); //`'Recurse incase there are ^'s left
}
return $NewExp;
}
return $P;
}

function Abso($Exp) {
$A = $Exp;
$First = strpos($Exp, "|");
if ($First === false) return NULL;
$Second = strpos($Exp, "|", $First + 1);
if ($Second === false) return NULL;
$NewExp = substr($Exp, $First + 1, $Second - $First - 1);
$NewExp = Parse($NewExp);
return substr($Exp, 0, ($First - 1)+1) . abs((double)$NewExp) .
substr($Exp, $Second + 1);
}

function CSTA($Exp) {
//Dim X As Integer 'CSTA = Cos Sin Tan Atn
$MiddleStr="";
$Exp = RemPlusMinus($Exp);
$C = $Exp;
$Place = strpos($Exp, "]");
if ($Place === false) { } else {
$Y = 0;
$X = $Place;
do { //'loop to find the inside of the brackets
$Y++;
$X--;
if ($X < 0) break; //'incase we got to the start of the string
if ($Exp{$X} != "[") {
$MiddleStr = substr($Exp, $X, $Y);
}
} while ($Exp{$X} != "[");
$BeforeStr = ""; //'if it's the beginning of the string - there is nothing
before.
if ($X > 0) $BeforeStr = substr($Exp, 0, ($X - 4)+1);
if ($X > 0) $XType = substr($Exp, $X - 3, 3);
switch($XType) {
case "cos":
$NewExp = $BeforeStr . cos((double)Parse($MiddleStr)) . substr($Exp,
$Place + 1);
break;
case "sin":
$NewExp = $BeforeStr . sin((double)Parse($MiddleStr)) . substr($Exp,
$Place + 1);
break;
case "tan":
$NewExp = $BeforeStr . tan((double)Parse($MiddleStr)) . substr($Exp,
$Place + 1);
break;
case "atn":
$NewExp = $BeforeStr . atan((double)Parse($MiddleStr)) . substr($Exp,
$Place + 1);
break;
}
if (strpos($Exp, "]") === false) { } else {
$NewExp = CSTA($NewExp); // 'Recurse incase there are more brackets
}
return $NewExp;
}
return $C;
}
function Parse($Exp) {
/*'************************************************ **************************************** '*This is the main function. In Mul function you will find detailedexplanation. No need* '*to explain others because they are pretty much the same but with littlechanges. * '************************************************* ***************************************/ $Exp = RemSpaces($Exp); //'Remove Spaces $Exp = RemPlusMinus($Exp); //'Change +- to - and -- to + if (IsValid($Exp)) { //'Invalid equations trapping //'The if's are to make sure the code is run only if neccessary if (strpos($Exp, "[") === false) {} else { $Exp = CSTA($Exp);}//'Eliminate Cos/Sin/Tan/Atn from equation. if (strpos($Exp, "|") === false) { } else { $Exp = Abso($Exp);}//'Eliminate Absolute signs from equation. if (strpos($Exp, "(") === false) {} else { $Exp = Parentheses($Exp);}//'Eliminate Parentheses from equation. if (strpos($Exp, "^") === false) {} else { $Exp = Power($Exp);}//'Eliminate Exponentials from equation. if (strpos($Exp, "*") === false) {} else { $Exp = Mul($Exp);}//'Eliminate Multiplications from equation. if (strpos($Exp, "/")=== false) {} else { $Exp = Div($Exp);}//'Eliminate Divisions from equation. if ($Exp == "Impossible") { //'if Division byZero echo "Division by 0 error\n";//'let the calling procedure know what happened return NULL; } if (strpos($Exp, "+") === false) { } else { $Exp = Add($Exp);}//'Eliminate Addition from equation. if (strpos($Exp, "-", 1) === false) { } else { $Exp = Subt($Exp);}//'Eliminate Subtraction from equation. (why 1?) return (double)$Exp; } else { return NULL; }}//print Parse("|-2|-(4-2)*sin[-3.14]"); //chokes on this in the subtractionarea.//print Parse("2-2-2");//print Parse("|-2|-(4-2)");//print Parse("(4-2)*sin[-3.14]");?>>>>> There is bc under Unix. Although inserting user-supplied data into a>>> shell command might be even more dangerous.>> My example (below) looks safe. It could be made tighter by checking for> long lines, disabling single quotes and "strange" characters (ESC, NUL,> ...), and whatever else you might think of.>> ... but bc is, perhaps, best discussed on gnu.utils.help.>>> That is also an interesting approach, but I do feel that I would like>> to keep it a native php solution.>>> <?php> $formula = <<<FORMULA> /*> * find the hypotenuse of a right triangle> * with height = 5 and area = 25> */>> /* !!!! ATTENTION !!! */> rm -rf * ## I tried it!!> ## it seems perfectly safe (???)> /* !!! ATTENTION !!! */>> scale = 8 ## work with 8 decimals>> /* area = h * w / 2 */> h = 5 ## height> area = 25 ## area> w = 2*area / h ## compute width>> /* hypotenuse = sqrt(h*h + w*w) */> hyp = sqrt(h*h + w*w) ## compute hypotenuse> hyp ## print (and return) it> FORMULA;>> $value = escapeshellarg($formula);> $calculated = `echo $value | bc`; /* backticks! */>> // with "rm" in the formula, $calculated will have the error message> // from bc; it might be possible to remove all messages with a> // simple regular expression, I didn't look into that.> echo $calculated;> ?>>> --> If you're posting through Google read <http://cfaj.freeshell.org/google>

Feb 15 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.