Hello I am building a PHP scientific calculator, users can perform calculation by just typing like normal mathematical expressions, e.g "(2+3-46)/33.3* 4!" so the result will be calculated accordingly, but I have a problem that, when malicious users try to put a mathematical expressions that is very long enough and takes a very heavy load of processing which might make my web server down. Such as

"9999999999999999999999999999999999999999999999999999999 * 999999999999999999999999999999"

So I thought of limiting the expressions that users can input up to 50 characters long, but this is still not a good idea, because heavy calculations does not necessarily depends on the length of the expressions, such as

//This does not make my computer load heavily even though it's long
"1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1"

//But this one consume high processing power and make my apache hang even it's short
"99999999999999"

So I want to know, is there a logic that can actually determines the result which might consume high processing which can solve my problem ? or is there a good scientific calculator library that you might want to share ? Thanks a lot.

    http://us.php.net/manual/en/ref.bc.php

    Have you actually tested the code to see which operations are slow and what the acceptable boundaries are for those operations? I think if you actually look at some data, the logic you want will become clear.

      It might not help all problems, but you could screen out any requests that use numbers above an arbitrary number of digits:

      if(preg_match('/\d{9,}/', $equation))
      {
         // too many conscutive digits
      }
      else
      {
         // OK
      }
      

        Thanks, for the reply
        When I tried it on my localhost, "99999999999999999999999999" it really makes my processors lights on without blinking for quite a few seconds and finally makes my apache hang for 1.83 Ghz Duo core processors with 1.5 GB RAM.
        I believe there must be logic, because you can try in Google, type "99999", it gives you result of calculation, but if you tried "999103" . Google won't give you the result, because it seems that they will not calculate expression that will give result that exceed around 9.02983468 × 10305
        I have used the BC math calculation as well.

        I have tried something out below but still not solving.
        Let's say 999999 will make my apache server hang, let the base and the power be x and y respectively, x ^ y
        So if I limit the x and y to be 900 respectively, 900900. so the the following should be OK
        800400
        700900
        2900

        since x or y are equal or less than 900
        But problem is this line below should be allowed too, because the result still less than 900900 and does not make heavy load.
        21000
        But since we limit the y to be 900, this will not be calculated, which is a bad idea too. I so eager to solve this, but so far have not get a good solutions, but I believe there is a logic like Google's. Thanks.

          You could probably try throwing a few heuristics to weed out obvious overflows, but there will always be some that get through (have you tried 999? No, it's not 1.96627E77.) After all, if you knew what the answer would be you wouldn't need to calculate it, would you?

          The only reliable way to "actually determine the result which might consume high processing" is to try it and see; anything else would end up requiring just as much processing and wouldn't even give you the result of the calculation.

          Google's "logic" is probably just to try and calculate it as an ordinary floating-point expression, and give up if it overflows (judging from the maximum size and precision of its results: 99999 is only approximately 9.05697845E296, after all).

            Without seeing any code it's hard to know exactly how to help but you might know already that (for example) ...

            y153 = (y100)(y50)(y3)

            So you could split the exponent into powers of ten (153 = 100 + 50 + 3), then cycle through them, multiplying as you go. Stop if the result is getting too big.

            P.

              Write a Reply...