Skip to content
This repository has been archived by the owner on Oct 15, 2022. It is now read-only.

Commit

Permalink
Calculator: Prevent anything but allowed ops in the query (#3903)
Browse files Browse the repository at this point in the history
* prevent anything but allowed ops in the query
no negative nums

* Uncomment neg catch and move after garbage is removed

* Add more tests

* The hex check can be simplified since the trigger isn't allowing most of it
Allow expressions like 1e9 to pass

* Allow = in query
decimal/negatives with e

* Remove debug

* add test for 1e9 query
  • Loading branch information
moollaza authored Jan 30, 2017
1 parent e905e28 commit 0ad6eba
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 12 deletions.
24 changes: 12 additions & 12 deletions lib/DDG/Goodie/Calculator.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ use utf8;
zci answer_type => 'calc';
zci is_cached => 1;

triggers query_nowhitespace => qr'
(?: [0-9 () x × ∙ ⋅ * % + \- ÷ / \^ \$ \. ,]+ |
triggers query_nowhitespace => qr'^
(?: [0-9 () x × ∙ ⋅ * % + \- ÷ / \^ \$ \. \, _ =]+ |
what is| calculate | solve | math |
times | divided by | plus | minus | fact | factorial | cos |
sin | tan | cotan | log | ln | log_?\d{1,3} | exp | tanh |
sec | csc | squared | sqrt | gross | dozen | pi |
score){2,}
sec | csc | squared | sqrt | gross | dozen | pi | e |
score){2,}$
'xi;

my $number_re = number_style_regex();
Expand Down Expand Up @@ -82,23 +83,23 @@ $safe->share_from('main', [qw'
handle query_nowhitespace => sub {
my $query = $_;

# regex source: http://perldoc.perl.org/functions/hex.html
return if ($req->query_lc =~ /\A(?:0?[xX])?(?:_?[0-9a-fA-F])*\z/); # Probably attempt to express a hexadecimal number, query_nowhitespace makes this overreach a bit.
return if $req->query_lc =~ /^0x/i; # hex maybe?
return if ($query =~ $network); # Probably want to talk about addresses, not calculations.
return if ($query =~ qr/(?:(?<pcnt>\d+)%(?<op>(\+|\-|\*|\/))(?<num>\d+)) | (?:(?<num>\d+)(?<op>(\+|\-|\*|\/))(?<pcnt>\d+)%)/); # Probably want to calculate a percent ( will be used PercentOf )
return if ($query =~ /^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/); # Probably are searching for a phone number, not making a calculation
return if $query =~ /[":\@]/;
return if $query =~ m{[x × ∙ ⋅ * % + \- ÷ / \^ \$ \. ,]{3,}}i;
return if $query =~ /\$[^\d\.]/;
return if $query =~ /\(\)/;

$query =~ s/^(?:whatis|calculate|solve|math)//i;

return if $query =~ /^(?:minus|-)\d+$/;

$query =~ s/factorial/fact/i; #replace factorial with fact

# Grab expression.
my $tmp_expr = spacing($query, 1);

return if $tmp_expr eq $query; # If it didn't get spaced out, there are no operations to be done.
return if ($tmp_expr eq $query) && ($query !~ /\de/i); # If it didn't get spaced out, there are no operations to be done.

# First replace named operations with their computable equivalents.
while (my ($name, $operation) = each %named_operations) {
Expand All @@ -107,7 +108,7 @@ handle query_nowhitespace => sub {
}

$tmp_expr =~ s#log[_]?(\d{1,3})#(1/log($1))*log#xg; # Arbitrary base logs.
$tmp_expr =~ s/ (\d+?)E(-?\d+)([^\d]|\b) /\($1 * 10**$2\)$3/ixg; # E == *10^n
$tmp_expr =~ s/([\d\.\-]+)E([\d\.\-]+)/\($1 * 10**$2\)/ig; # E == *10^n
$tmp_expr =~ s/\$//g; # Remove $s.
$tmp_expr =~ s/=$//; # Drop =.
$tmp_expr =~ s/([0-9])\s*([a-zA-Z])([^0-9])/$1*$2$3/g; # Support 0.5e or 0.5pi; but don't break 1e8
Expand All @@ -117,7 +118,6 @@ handle query_nowhitespace => sub {
$tmp_expr =~ s#\b$name\b# $constant #ig;
$query =~ s#\b$name\b#($name)#ig;
}

my @numbers = grep { $_ =~ /^$number_re$/ } (split /\s+/, $tmp_expr);
my $style = number_style_for(@numbers);
return unless $style;
Expand Down Expand Up @@ -162,7 +162,7 @@ sub prepare_for_display {
$query =~ s/\=$//;
$query =~ s/(\d)[ _](\d)/$1$2/g; # Squeeze out spaces and underscores.
# Show them how 'E' was interpreted. This should use the number styler, too.
$query =~ s/((?:\d+?|\s))E(-?\d+)/\($1 * 10^$2\)/i;
$query =~ s/([\d\.\-]+)E([\-\d\.]+)/\($1 * 10^$2\)/ig;
$query =~ s/\s*\*\*\s*/^/g; # Use prettier exponentiation.
$query =~ s/Math::BigInt->new\(([^)]+)\)/fact\($1\)/g; #replace Math::BigInt->new( with fact(
$result = $style->for_display($result);
Expand Down
13 changes: 13 additions & 0 deletions t/Calculator.t
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,15 @@ ddg_goodie_test(
result => re(qr/>-30</)
}
),
'1e9' => test_zci(
'(1 * 10 ^ 9) = 1,000,000,000',
heading => 'Calculator',
structured_answer => {
input => ['(1 * 10 ^ 9)'],
operation => 'Calculate',
result => re(qr/>1,000,000,000</)
}
),
'123.123.123.123/255.255.255.255' => undef,
'83.166.167.160/27' => undef,
'9 + 0 x 0xbf7' => undef,
Expand Down Expand Up @@ -890,6 +899,10 @@ ddg_goodie_test(
'word+word' => undef,
'word + word' => undef,
'mxtoolbox' => undef,
'fx-es' => undef,
'-2' => undef,
'-0' => undef,
'm.box.com' => undef,
);

done_testing;

0 comments on commit 0ad6eba

Please sign in to comment.