[Forensics-changes] [yara] 265/407: Add new instructions for working with doubles.

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:28:33 UTC 2017


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag v3.3.0
in repository yara.

commit 86d991e105b74f50636fef8152f0fc021033432b
Author: Wesley Shields <wxs at atarininja.org>
Date:   Mon Dec 29 14:02:30 2014 -0500

    Add new instructions for working with doubles.
---
 libyara/exec.c              | 132 ++++++++-
 libyara/grammar.c           | 696 +++++++++++++++++++++++++++++++++-----------
 libyara/grammar.y           | 509 +++++++++++++++++++++++++++-----
 libyara/include/yara/exec.h |  11 +
 4 files changed, 1094 insertions(+), 254 deletions(-)

diff --git a/libyara/exec.c b/libyara/exec.c
index 2e5f6c4..03ab59b 100644
--- a/libyara/exec.c
+++ b/libyara/exec.c
@@ -43,9 +43,57 @@ limitations under the License.
     } while(0)
 
 
+// Used when pushing a double to the stack, which looses precision when
+// using push().
+#define push_dbl(x)  \
+    do { \
+      if (sp < STACK_SIZE) \
+      { \
+        dsp = (double*) (stack + sp); \
+        *dsp = (x); \
+        sp++; \
+      } \
+      else return ERROR_EXEC_STACK_OVERFLOW; \
+    } while(0)
+
+
 #define pop(x)  x = stack[--sp]
 
 
+#define pop_dbl(x)  x = *(double*) &stack[--sp]
+
+
+// The _rel() variants are used to push or pop at specific offsets from sp.
+// This is useful when you need have a stack with an integer that needs to be
+// converted to a double at stack[0] and a double at stack[1]. In this case
+// sp would be 2, so you can do:
+//
+// pop_rel(2, r1)
+// push_dbl_rel(2, r1)
+#define push_rel(offset, x) \
+    do { \
+      if (offset <= 0 || sp - offset < 0) return ERROR_EXEC_STACK_OVERFLOW; \
+      else stack[sp - offset] = (x); \
+    } while(0)
+
+
+#define push_dbl_rel(offset, x) \
+    do { \
+      if (offset <= 0 || sp - offset < 0) return ERROR_EXEC_STACK_OVERFLOW; \
+      else \
+      { \
+        dsp = (double *) ((stack + sp) - offset); \
+        *dsp = (x); \
+      } \
+    } while(0)
+
+#define pop_rel(offset, x) \
+    do { \
+      if (offset < 0 || sp - offset < 0) return ERROR_EXEC_STACK_OVERFLOW; \
+      else x = stack[sp - offset]; \
+    } while(0)
+
+
 #define little_endian_uint8_t(x)     (x)
 #define little_endian_uint16_t(x)    (x)
 #define little_endian_uint32_t(x)    (x)
@@ -112,8 +160,11 @@ int yr_execute_code(
   int64_t r1;
   int64_t r2;
   int64_t r3;
+  double dr1;
+  double dr2;
   int64_t mem[MEM_SIZE];
   int64_t stack[STACK_SIZE];
+  double* dsp = 0;
   int64_t args[MAX_FUNCTION_ARGS];
   int32_t sp = 0;
   uint8_t* ip = rules->code_start;
@@ -499,7 +550,7 @@ int yr_execute_code(
             break;
 
           case OBJECT_TYPE_DOUBLE:
-            push(((YR_OBJECT_DOUBLE*) object)->value);
+            push_dbl(((YR_OBJECT_DOUBLE*) object)->value);
             break;
 
           case OBJECT_TYPE_STRING:
@@ -864,6 +915,85 @@ int yr_execute_code(
         push(result >= 0);
         break;
 
+      case OP_ITD:
+        r1 = *(uint64_t*)(ip + 1);
+        ip += sizeof(uint64_t);
+
+        pop_rel(r1, r2);
+
+        if (IS_UNDEFINED(r2))
+        {
+          push(UNDEFINED);
+        }
+        else
+        {
+          push_dbl_rel(r1, r2);
+        }
+        break;
+
+      // Double comparisons do not use push_dbl because the result is just
+      // an integer.
+      case OP_LTD:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push(COMPARISON(<, dr1, dr2));
+        break;
+
+      case OP_GTD:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push(COMPARISON(>, dr1, dr2));
+        break;
+
+      case OP_LED:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push(COMPARISON(<=, dr1, dr2));
+        break;
+
+      case OP_GED:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push(COMPARISON(>=, dr1, dr2));
+        break;
+
+      case OP_EQD:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push(COMPARISON(==, dr1, dr2));
+        break;
+
+      case OP_NEQD:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push(COMPARISON(!=, dr1, dr2));
+        break;
+
+      // Double operations do use push_dbl because the result is a double.
+      case OP_ADD_DBL:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push_dbl(OPERATION(+, dr1, dr2));
+        break;
+
+      case OP_SUB_DBL:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push_dbl(OPERATION(-, dr1, dr2));
+        break;
+
+      case OP_MUL_DBL:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push_dbl(OPERATION(*, dr1, dr2));
+        break;
+
+      case OP_DIV_DBL:
+        pop_dbl(dr2);
+        pop_dbl(dr1);
+        push_dbl(OPERATION(/, dr1, dr2));
+        break;
+
       default:
         // Unknown instruction, this shouldn't happen.
         assert(FALSE);
diff --git a/libyara/grammar.c b/libyara/grammar.c
index 1494f21..22f3e3c 100644
--- a/libyara/grammar.c
+++ b/libyara/grammar.c
@@ -640,12 +640,12 @@ static const yytype_uint16 yyrline[] =
      488,   493,   507,   506,   525,   542,   543,   548,   549,   550,
      551,   556,   644,   692,   752,   799,   802,   827,   863,   908,
      925,   934,   943,   958,   972,   986,  1002,  1017,  1052,  1016,
-    1166,  1165,  1244,  1250,  1256,  1262,  1270,  1288,  1306,  1324,
-    1342,  1369,  1396,  1423,  1427,  1435,  1436,  1441,  1463,  1475,
-    1491,  1490,  1496,  1505,  1506,  1511,  1516,  1525,  1526,  1530,
-    1538,  1542,  1552,  1565,  1581,  1591,  1601,  1624,  1639,  1654,
-    1676,  1718,  1728,  1738,  1748,  1758,  1768,  1778,  1788,  1798,
-    1808,  1818,  1828
+    1166,  1165,  1244,  1250,  1256,  1262,  1270,  1324,  1377,  1431,
+    1485,  1543,  1571,  1629,  1633,  1641,  1642,  1647,  1669,  1681,
+    1697,  1696,  1702,  1711,  1712,  1717,  1722,  1731,  1732,  1736,
+    1744,  1748,  1758,  1771,  1787,  1797,  1807,  1830,  1845,  1860,
+    1882,  1924,  1970,  2016,  2062,  2108,  2118,  2128,  2138,  2148,
+    2158,  2168,  2178
 };
 #endif
 
@@ -2840,125 +2840,300 @@ yyreduce:
   case 66:
 #line 1271 "grammar.y" /* yacc.c:1661  */
     {
-        if (CHECK_TYPE_NO_CLEANUP((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP((yyvsp[-2].expression), EXPRESSION_TYPE_DOUBLE))
+        if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
         {
-          CLEANUP("<", (yyvsp[-2].expression));
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for < operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LTD, NULL);
         }
-        if (CHECK_TYPE_NO_CLEANUP((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP((yyvsp[0].expression), EXPRESSION_TYPE_DOUBLE))
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
         {
-          CLEANUP("<", (yyvsp[0].expression));
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LT, NULL);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LTD, NULL);
+        }
+        else
+        {
+          CLEANUP("<", (yyvsp[-2].expression));
         }
-        TYPE_INEQUALITY((yyvsp[-2].expression), (yyvsp[0].expression), "<")
 
-        yr_parser_emit(yyscanner, OP_LT, NULL);
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
         (yyval.expression).type = EXPRESSION_TYPE_BOOLEAN;
       }
-#line 2860 "grammar.c" /* yacc.c:1661  */
+#line 2896 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 67:
-#line 1289 "grammar.y" /* yacc.c:1661  */
+#line 1325 "grammar.y" /* yacc.c:1661  */
     {
-        if (CHECK_TYPE_NO_CLEANUP((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP((yyvsp[-2].expression), EXPRESSION_TYPE_DOUBLE))
+        if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
         {
-          CLEANUP(">", (yyvsp[-2].expression));
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for > operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GTD, NULL);
         }
-        if (CHECK_TYPE_NO_CLEANUP((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP((yyvsp[0].expression), EXPRESSION_TYPE_DOUBLE))
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
         {
-          CLEANUP(">", (yyvsp[0].expression));
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GT, NULL);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GTD, NULL);
+        }
+        else
+        {
+          CLEANUP(">", (yyvsp[-2].expression));
         }
-        TYPE_INEQUALITY((yyvsp[-2].expression), (yyvsp[0].expression), ">")
-
-        yr_parser_emit(yyscanner, OP_GT, NULL);
 
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
         (yyval.expression).type = EXPRESSION_TYPE_BOOLEAN;
       }
-#line 2882 "grammar.c" /* yacc.c:1661  */
+#line 2953 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 68:
-#line 1307 "grammar.y" /* yacc.c:1661  */
+#line 1378 "grammar.y" /* yacc.c:1661  */
     {
-        if (CHECK_TYPE_NO_CLEANUP((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP((yyvsp[-2].expression), EXPRESSION_TYPE_DOUBLE))
+        if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
         {
-          CLEANUP("<=", (yyvsp[-2].expression));
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for <= operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LED, NULL);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LE, NULL);
         }
-        if (CHECK_TYPE_NO_CLEANUP((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP((yyvsp[0].expression), EXPRESSION_TYPE_DOUBLE))
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
         {
-          CLEANUP("<=", (yyvsp[0].expression));
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LED, NULL);
+        }
+        else
+        {
+          CLEANUP("<=", (yyvsp[-2].expression));
         }
-        TYPE_INEQUALITY((yyvsp[-2].expression), (yyvsp[0].expression), "<=")
 
-        yr_parser_emit(yyscanner, OP_LE, NULL);
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
         (yyval.expression).type = EXPRESSION_TYPE_BOOLEAN;
       }
-#line 2904 "grammar.c" /* yacc.c:1661  */
+#line 3011 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 69:
-#line 1325 "grammar.y" /* yacc.c:1661  */
+#line 1432 "grammar.y" /* yacc.c:1661  */
     {
-        if (CHECK_TYPE_NO_CLEANUP((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP((yyvsp[-2].expression), EXPRESSION_TYPE_DOUBLE))
+        if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
         {
-          CLEANUP(">=", (yyvsp[-2].expression));
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for >= operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GED, NULL);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GE, NULL);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GED, NULL);
         }
-        if (CHECK_TYPE_NO_CLEANUP((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP((yyvsp[0].expression), EXPRESSION_TYPE_DOUBLE))
+        else
         {
-          CLEANUP(">=", (yyvsp[0].expression));
+          CLEANUP(">=", (yyvsp[-2].expression));
         }
-        TYPE_INEQUALITY((yyvsp[-2].expression), (yyvsp[0].expression), ">=")
 
-        yr_parser_emit(yyscanner, OP_GE, NULL);
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
         (yyval.expression).type = EXPRESSION_TYPE_BOOLEAN;
       }
-#line 2926 "grammar.c" /* yacc.c:1661  */
+#line 3069 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 70:
-#line 1343 "grammar.y" /* yacc.c:1661  */
+#line 1486 "grammar.y" /* yacc.c:1661  */
     {
         if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
         {
-          yr_compiler_set_error_extra_info(
-              compiler, "mismatching types for == operator");
-          compiler->last_result = ERROR_WRONG_TYPE;
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for == operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_EQD, NULL);
         }
         else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_STRING)
         {
-          compiler->last_result = yr_parser_emit(
-              yyscanner,
-              OP_STR_EQ,
-              NULL);
+          compiler->last_result = yr_parser_emit(yyscanner, OP_STR_EQ, NULL);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_EQ, NULL);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_EQD, NULL);
         }
         else
         {
-          compiler->last_result = yr_parser_emit(
-              yyscanner,
-              OP_EQ,
-              NULL);
+          CLEANUP("==", (yyvsp[-2].expression));
         }
 
         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
         (yyval.expression).type = EXPRESSION_TYPE_BOOLEAN;
       }
-#line 2957 "grammar.c" /* yacc.c:1661  */
+#line 3131 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 71:
-#line 1370 "grammar.y" /* yacc.c:1661  */
+#line 1544 "grammar.y" /* yacc.c:1661  */
     {
+        // XXX: What is _IS_? Dead code?
         if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
         {
           yr_compiler_set_error_extra_info(
@@ -2984,70 +3159,101 @@ yyreduce:
 
         (yyval.expression).type = EXPRESSION_TYPE_BOOLEAN;
       }
-#line 2988 "grammar.c" /* yacc.c:1661  */
+#line 3163 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 72:
-#line 1397 "grammar.y" /* yacc.c:1661  */
+#line 1572 "grammar.y" /* yacc.c:1661  */
     {
         if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
         {
-          yr_compiler_set_error_extra_info(
-              compiler, "mismatching types for != operator");
-          compiler->last_result = ERROR_WRONG_TYPE;
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for != operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_NEQD, NULL);
         }
         else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_STRING)
         {
-          compiler->last_result = yr_parser_emit(
-              yyscanner,
-              OP_STR_NEQ,
-              NULL);
+          compiler->last_result = yr_parser_emit(yyscanner, OP_STR_NEQ, NULL);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_NEQ, NULL);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_NEQD, NULL);
         }
         else
         {
-          compiler->last_result = yr_parser_emit(
-              yyscanner,
-              OP_NEQ,
-              NULL);
+          CLEANUP("!=", (yyvsp[-2].expression));
         }
 
         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
         (yyval.expression).type = EXPRESSION_TYPE_BOOLEAN;
       }
-#line 3019 "grammar.c" /* yacc.c:1661  */
+#line 3225 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 73:
-#line 1424 "grammar.y" /* yacc.c:1661  */
+#line 1630 "grammar.y" /* yacc.c:1661  */
     {
         (yyval.expression) = (yyvsp[0].expression);
       }
-#line 3027 "grammar.c" /* yacc.c:1661  */
+#line 3233 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 74:
-#line 1428 "grammar.y" /* yacc.c:1661  */
+#line 1634 "grammar.y" /* yacc.c:1661  */
     {
         (yyval.expression) = (yyvsp[-1].expression);
       }
-#line 3035 "grammar.c" /* yacc.c:1661  */
+#line 3241 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 75:
-#line 1435 "grammar.y" /* yacc.c:1661  */
+#line 1641 "grammar.y" /* yacc.c:1661  */
     { (yyval.integer) = INTEGER_SET_ENUMERATION; }
-#line 3041 "grammar.c" /* yacc.c:1661  */
+#line 3247 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 76:
-#line 1436 "grammar.y" /* yacc.c:1661  */
+#line 1642 "grammar.y" /* yacc.c:1661  */
     { (yyval.integer) = INTEGER_SET_RANGE; }
-#line 3047 "grammar.c" /* yacc.c:1661  */
+#line 3253 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 77:
-#line 1442 "grammar.y" /* yacc.c:1661  */
+#line 1648 "grammar.y" /* yacc.c:1661  */
     {
         if ((yyvsp[-4].expression).type != EXPRESSION_TYPE_INTEGER)
         {
@@ -3065,11 +3271,11 @@ yyreduce:
 
         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
       }
-#line 3069 "grammar.c" /* yacc.c:1661  */
+#line 3275 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 78:
-#line 1464 "grammar.y" /* yacc.c:1661  */
+#line 1670 "grammar.y" /* yacc.c:1661  */
     {
         if ((yyvsp[0].expression).type != EXPRESSION_TYPE_INTEGER)
         {
@@ -3081,11 +3287,11 @@ yyreduce:
 
         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
       }
-#line 3085 "grammar.c" /* yacc.c:1661  */
+#line 3291 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 79:
-#line 1476 "grammar.y" /* yacc.c:1661  */
+#line 1682 "grammar.y" /* yacc.c:1661  */
     {
         if ((yyvsp[0].expression).type != EXPRESSION_TYPE_INTEGER)
         {
@@ -3096,71 +3302,71 @@ yyreduce:
 
         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
       }
-#line 3100 "grammar.c" /* yacc.c:1661  */
+#line 3306 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 80:
-#line 1491 "grammar.y" /* yacc.c:1661  */
+#line 1697 "grammar.y" /* yacc.c:1661  */
     {
         // Push end-of-list marker
         yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
       }
-#line 3109 "grammar.c" /* yacc.c:1661  */
+#line 3315 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 82:
-#line 1497 "grammar.y" /* yacc.c:1661  */
+#line 1703 "grammar.y" /* yacc.c:1661  */
     {
         yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
         yr_parser_emit_pushes_for_strings(yyscanner, "$*");
       }
-#line 3118 "grammar.c" /* yacc.c:1661  */
+#line 3324 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 85:
-#line 1512 "grammar.y" /* yacc.c:1661  */
+#line 1718 "grammar.y" /* yacc.c:1661  */
     {
         yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[0].c_string));
         yr_free((yyvsp[0].c_string));
       }
-#line 3127 "grammar.c" /* yacc.c:1661  */
+#line 3333 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 86:
-#line 1517 "grammar.y" /* yacc.c:1661  */
+#line 1723 "grammar.y" /* yacc.c:1661  */
     {
         yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[0].c_string));
         yr_free((yyvsp[0].c_string));
       }
-#line 3136 "grammar.c" /* yacc.c:1661  */
+#line 3342 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 88:
-#line 1527 "grammar.y" /* yacc.c:1661  */
+#line 1733 "grammar.y" /* yacc.c:1661  */
     {
         yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
       }
-#line 3144 "grammar.c" /* yacc.c:1661  */
+#line 3350 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 89:
-#line 1531 "grammar.y" /* yacc.c:1661  */
+#line 1737 "grammar.y" /* yacc.c:1661  */
     {
         yr_parser_emit_with_arg(yyscanner, OP_PUSH, 1, NULL);
       }
-#line 3152 "grammar.c" /* yacc.c:1661  */
+#line 3358 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 90:
-#line 1539 "grammar.y" /* yacc.c:1661  */
+#line 1745 "grammar.y" /* yacc.c:1661  */
     {
         (yyval.expression) = (yyvsp[-1].expression);
       }
-#line 3160 "grammar.c" /* yacc.c:1661  */
+#line 3366 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 91:
-#line 1543 "grammar.y" /* yacc.c:1661  */
+#line 1749 "grammar.y" /* yacc.c:1661  */
     {
         compiler->last_result = yr_parser_emit(
             yyscanner, OP_FILESIZE, NULL);
@@ -3170,11 +3376,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = UNDEFINED;
       }
-#line 3174 "grammar.c" /* yacc.c:1661  */
+#line 3380 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 92:
-#line 1553 "grammar.y" /* yacc.c:1661  */
+#line 1759 "grammar.y" /* yacc.c:1661  */
     {
         yywarning(yyscanner,
             "Using deprecated \"entrypoint\" keyword. Use the \"entry_point\" " "function from PE module instead.");
@@ -3187,11 +3393,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = UNDEFINED;
       }
-#line 3191 "grammar.c" /* yacc.c:1661  */
+#line 3397 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 93:
-#line 1566 "grammar.y" /* yacc.c:1661  */
+#line 1772 "grammar.y" /* yacc.c:1661  */
     {
         CHECK_TYPE((yyvsp[-1].expression), EXPRESSION_TYPE_INTEGER, "intXXXX or uintXXXX");
 
@@ -3207,11 +3413,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = UNDEFINED;
       }
-#line 3211 "grammar.c" /* yacc.c:1661  */
+#line 3417 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 94:
-#line 1582 "grammar.y" /* yacc.c:1661  */
+#line 1788 "grammar.y" /* yacc.c:1661  */
     {
         compiler->last_result = yr_parser_emit_with_arg(
             yyscanner, OP_PUSH, (yyvsp[0].integer), NULL);
@@ -3221,11 +3427,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = (yyvsp[0].integer);
       }
-#line 3225 "grammar.c" /* yacc.c:1661  */
+#line 3431 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 95:
-#line 1592 "grammar.y" /* yacc.c:1661  */
+#line 1798 "grammar.y" /* yacc.c:1661  */
     {
         compiler->last_result = yr_parser_emit_with_arg_double(
             yyscanner, OP_PUSH, (yyvsp[0].double_), NULL);
@@ -3235,11 +3441,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
         (yyval.expression).value.double_ = (yyvsp[0].double_);
       }
-#line 3239 "grammar.c" /* yacc.c:1661  */
+#line 3445 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 96:
-#line 1602 "grammar.y" /* yacc.c:1661  */
+#line 1808 "grammar.y" /* yacc.c:1661  */
     {
         SIZED_STRING* sized_string;
 
@@ -3262,11 +3468,11 @@ yyreduce:
 
         (yyval.expression).type = EXPRESSION_TYPE_STRING;
       }
-#line 3266 "grammar.c" /* yacc.c:1661  */
+#line 3472 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 97:
-#line 1625 "grammar.y" /* yacc.c:1661  */
+#line 1831 "grammar.y" /* yacc.c:1661  */
     {
         compiler->last_result = yr_parser_reduce_string_identifier(
             yyscanner,
@@ -3281,11 +3487,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = UNDEFINED;
       }
-#line 3285 "grammar.c" /* yacc.c:1661  */
+#line 3491 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 98:
-#line 1640 "grammar.y" /* yacc.c:1661  */
+#line 1846 "grammar.y" /* yacc.c:1661  */
     {
         compiler->last_result = yr_parser_reduce_string_identifier(
             yyscanner,
@@ -3300,11 +3506,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = UNDEFINED;
       }
-#line 3304 "grammar.c" /* yacc.c:1661  */
+#line 3510 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 99:
-#line 1655 "grammar.y" /* yacc.c:1661  */
+#line 1861 "grammar.y" /* yacc.c:1661  */
     {
         compiler->last_result = yr_parser_emit_with_arg(
             yyscanner,
@@ -3326,11 +3532,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = UNDEFINED;
       }
-#line 3330 "grammar.c" /* yacc.c:1661  */
+#line 3536 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 100:
-#line 1677 "grammar.y" /* yacc.c:1661  */
+#line 1883 "grammar.y" /* yacc.c:1661  */
     {
         if ((yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)  // loop identifier
         {
@@ -3355,7 +3561,7 @@ yyreduce:
               break;
             case OBJECT_TYPE_DOUBLE:
               (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
-              (yyval.expression).value.integer = UNDEFINED;
+              (yyval.expression).value.double_ = UNDEFINED;
               break;
             case OBJECT_TYPE_STRING:
               (yyval.expression).type = EXPRESSION_TYPE_STRING;
@@ -3372,67 +3578,211 @@ yyreduce:
 
         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
       }
-#line 3376 "grammar.c" /* yacc.c:1661  */
+#line 3582 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 101:
-#line 1719 "grammar.y" /* yacc.c:1661  */
+#line 1925 "grammar.y" /* yacc.c:1661  */
     {
-        CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, "+");
-        CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "+");
-
-        yr_parser_emit(yyscanner, OP_ADD, NULL);
+        if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
+        {
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 2, NULL);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 1, NULL);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for + operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
 
-        (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
-        (yyval.expression).value.integer = OPERATION(+, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
+          yr_parser_emit(yyscanner, OP_ADD_DBL, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
+          (yyval.expression).value.double_ = OPERATION(+, (yyvsp[-2].expression).value.double_, (yyvsp[0].expression).value.double_);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
+        {
+          yr_parser_emit(yyscanner, OP_ADD, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
+          (yyval.expression).value.integer = OPERATION(+, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
+        {
+          yr_parser_emit(yyscanner, OP_ADD_DBL, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
+          (yyval.expression).value.double_ = OPERATION(+, (yyvsp[-2].expression).value.double_, (yyvsp[0].expression).value.double_);
+        }
+        else
+        {
+          CLEANUP("+", (yyvsp[-2].expression));
+        }
       }
-#line 3390 "grammar.c" /* yacc.c:1661  */
+#line 3632 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 102:
-#line 1729 "grammar.y" /* yacc.c:1661  */
+#line 1971 "grammar.y" /* yacc.c:1661  */
     {
-        CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, "-");
-        CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "-");
-
-        yr_parser_emit(yyscanner, OP_SUB, NULL);
+        if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
+        {
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 2, NULL);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 1, NULL);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for - operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
 
-        (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
-        (yyval.expression).value.integer = OPERATION(-, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
+          yr_parser_emit(yyscanner, OP_SUB_DBL, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
+          (yyval.expression).value.double_ = OPERATION(-, (yyvsp[-2].expression).value.double_, (yyvsp[0].expression).value.double_);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
+        {
+          yr_parser_emit(yyscanner, OP_SUB, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
+          (yyval.expression).value.integer = OPERATION(-, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
+        {
+          yr_parser_emit(yyscanner, OP_SUB_DBL, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
+          (yyval.expression).value.double_ = OPERATION(-, (yyvsp[-2].expression).value.double_, (yyvsp[0].expression).value.double_);
+        }
+        else
+        {
+          CLEANUP("-", (yyvsp[-2].expression));
+        }
       }
-#line 3404 "grammar.c" /* yacc.c:1661  */
+#line 3682 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 103:
-#line 1739 "grammar.y" /* yacc.c:1661  */
+#line 2017 "grammar.y" /* yacc.c:1661  */
     {
-        CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, "*");
-        CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "*");
-
-        yr_parser_emit(yyscanner, OP_MUL, NULL);
+        if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
+        {
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 2, NULL);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 1, NULL);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for * operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
 
-        (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
-        (yyval.expression).value.integer = OPERATION(*, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
+          yr_parser_emit(yyscanner, OP_MUL_DBL, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
+          (yyval.expression).value.double_ = OPERATION(*, (yyvsp[-2].expression).value.double_, (yyvsp[0].expression).value.double_);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
+        {
+          yr_parser_emit(yyscanner, OP_MUL, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
+          (yyval.expression).value.integer = OPERATION(*, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
+        {
+          yr_parser_emit(yyscanner, OP_MUL_DBL, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
+          (yyval.expression).value.double_ = OPERATION(*, (yyvsp[-2].expression).value.double_, (yyvsp[0].expression).value.double_);
+        }
+        else
+        {
+          CLEANUP("*", (yyvsp[-2].expression));
+        }
       }
-#line 3418 "grammar.c" /* yacc.c:1661  */
+#line 3732 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 104:
-#line 1749 "grammar.y" /* yacc.c:1661  */
+#line 2063 "grammar.y" /* yacc.c:1661  */
     {
-        CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, "\\");
-        CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "\\");
-
-        yr_parser_emit(yyscanner, OP_DIV, NULL);
+        if ((yyvsp[-2].expression).type != (yyvsp[0].expression).type)
+        {
+          if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER &&
+              (yyvsp[0].expression).type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 2, NULL);
+          }
+          else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE &&
+                   (yyvsp[0].expression).type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 1, NULL);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for \\ operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
 
-        (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
-        (yyval.expression).value.integer = OPERATION(/, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
+          yr_parser_emit(yyscanner, OP_DIV_DBL, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
+          (yyval.expression).value.double_ = OPERATION(/, (yyvsp[-2].expression).value.double_, (yyvsp[0].expression).value.double_);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_INTEGER)
+        {
+          yr_parser_emit(yyscanner, OP_DIV, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
+          (yyval.expression).value.integer = OPERATION(*, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
+        }
+        else if ((yyvsp[-2].expression).type == EXPRESSION_TYPE_DOUBLE)
+        {
+          yr_parser_emit(yyscanner, OP_DIV_DBL, NULL);
+          (yyval.expression).type = EXPRESSION_TYPE_DOUBLE;
+          (yyval.expression).value.double_ = OPERATION(/, (yyvsp[-2].expression).value.double_, (yyvsp[0].expression).value.double_);
+        }
+        else
+        {
+          CLEANUP("\\", (yyvsp[-2].expression));
+        }
       }
-#line 3432 "grammar.c" /* yacc.c:1661  */
+#line 3782 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 105:
-#line 1759 "grammar.y" /* yacc.c:1661  */
+#line 2109 "grammar.y" /* yacc.c:1661  */
     {
         CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, "%");
         CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "%");
@@ -3442,11 +3792,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = OPERATION(%, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
       }
-#line 3446 "grammar.c" /* yacc.c:1661  */
+#line 3796 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 106:
-#line 1769 "grammar.y" /* yacc.c:1661  */
+#line 2119 "grammar.y" /* yacc.c:1661  */
     {
         CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, "^");
         CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "^");
@@ -3456,11 +3806,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = OPERATION(^, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
       }
-#line 3460 "grammar.c" /* yacc.c:1661  */
+#line 3810 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 107:
-#line 1779 "grammar.y" /* yacc.c:1661  */
+#line 2129 "grammar.y" /* yacc.c:1661  */
     {
         CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, "^");
         CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "^");
@@ -3470,11 +3820,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = OPERATION(&, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
       }
-#line 3474 "grammar.c" /* yacc.c:1661  */
+#line 3824 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 108:
-#line 1789 "grammar.y" /* yacc.c:1661  */
+#line 2139 "grammar.y" /* yacc.c:1661  */
     {
         CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, "|");
         CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "|");
@@ -3484,11 +3834,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = OPERATION(|, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
       }
-#line 3488 "grammar.c" /* yacc.c:1661  */
+#line 3838 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 109:
-#line 1799 "grammar.y" /* yacc.c:1661  */
+#line 2149 "grammar.y" /* yacc.c:1661  */
     {
         CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "~");
 
@@ -3498,11 +3848,11 @@ yyreduce:
         (yyval.expression).value.integer = ((yyvsp[0].expression).value.integer == UNDEFINED) ?
                               UNDEFINED : (yyvsp[0].expression).value.integer;
       }
-#line 3502 "grammar.c" /* yacc.c:1661  */
+#line 3852 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 110:
-#line 1809 "grammar.y" /* yacc.c:1661  */
+#line 2159 "grammar.y" /* yacc.c:1661  */
     {
         CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, "<<");
         CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, "<<");
@@ -3512,11 +3862,11 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = OPERATION(<<, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
       }
-#line 3516 "grammar.c" /* yacc.c:1661  */
+#line 3866 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 111:
-#line 1819 "grammar.y" /* yacc.c:1661  */
+#line 2169 "grammar.y" /* yacc.c:1661  */
     {
         CHECK_TYPE((yyvsp[-2].expression), EXPRESSION_TYPE_INTEGER, ">>");
         CHECK_TYPE((yyvsp[0].expression), EXPRESSION_TYPE_INTEGER, ">>");
@@ -3526,19 +3876,19 @@ yyreduce:
         (yyval.expression).type = EXPRESSION_TYPE_INTEGER;
         (yyval.expression).value.integer = OPERATION(>>, (yyvsp[-2].expression).value.integer, (yyvsp[0].expression).value.integer);
       }
-#line 3530 "grammar.c" /* yacc.c:1661  */
+#line 3880 "grammar.c" /* yacc.c:1661  */
     break;
 
   case 112:
-#line 1829 "grammar.y" /* yacc.c:1661  */
+#line 2179 "grammar.y" /* yacc.c:1661  */
     {
         (yyval.expression) = (yyvsp[0].expression);
       }
-#line 3538 "grammar.c" /* yacc.c:1661  */
+#line 3888 "grammar.c" /* yacc.c:1661  */
     break;
 
 
-#line 3542 "grammar.c" /* yacc.c:1661  */
+#line 3892 "grammar.c" /* yacc.c:1661  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -3766,5 +4116,5 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 1834 "grammar.y" /* yacc.c:1906  */
+#line 2184 "grammar.y" /* yacc.c:1906  */
 
diff --git a/libyara/grammar.y b/libyara/grammar.y
index 340d591..941ff9b 100644
--- a/libyara/grammar.y
+++ b/libyara/grammar.y
@@ -1269,73 +1269,216 @@ expression
       }
     | primary_expression _LT_ primary_expression
       {
-        if (CHECK_TYPE_NO_CLEANUP($1, EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP($1, EXPRESSION_TYPE_DOUBLE))
+        if ($1.type != $3.type)
         {
-          CLEANUP("<", $1);
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for < operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LTD, NULL);
+        }
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LT, NULL);
+        }
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LTD, NULL);
         }
-        if (CHECK_TYPE_NO_CLEANUP($3, EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP($3, EXPRESSION_TYPE_DOUBLE))
+        else
         {
-          CLEANUP("<", $3);
+          CLEANUP("<", $1);
         }
-        TYPE_INEQUALITY($1, $3, "<")
 
-        yr_parser_emit(yyscanner, OP_LT, NULL);
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
         $$.type = EXPRESSION_TYPE_BOOLEAN;
       }
     | primary_expression _GT_ primary_expression
       {
-        if (CHECK_TYPE_NO_CLEANUP($1, EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP($1, EXPRESSION_TYPE_DOUBLE))
+        if ($1.type != $3.type)
         {
-          CLEANUP(">", $1);
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for > operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GTD, NULL);
         }
-        if (CHECK_TYPE_NO_CLEANUP($3, EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP($3, EXPRESSION_TYPE_DOUBLE))
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
         {
-          CLEANUP(">", $3);
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GT, NULL);
+        }
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GTD, NULL);
+        }
+        else
+        {
+          CLEANUP(">", $1);
         }
-        TYPE_INEQUALITY($1, $3, ">")
-
-        yr_parser_emit(yyscanner, OP_GT, NULL);
 
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
         $$.type = EXPRESSION_TYPE_BOOLEAN;
       }
     | primary_expression _LE_ primary_expression
       {
-        if (CHECK_TYPE_NO_CLEANUP($1, EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP($1, EXPRESSION_TYPE_DOUBLE))
+        if ($1.type != $3.type)
         {
-          CLEANUP("<=", $1);
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for <= operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LED, NULL);
+        }
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LE, NULL);
         }
-        if (CHECK_TYPE_NO_CLEANUP($3, EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP($3, EXPRESSION_TYPE_DOUBLE))
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
         {
-          CLEANUP("<=", $3);
+          compiler->last_result = yr_parser_emit(yyscanner, OP_LED, NULL);
+        }
+        else
+        {
+          CLEANUP("<=", $1);
         }
-        TYPE_INEQUALITY($1, $3, "<=")
 
-        yr_parser_emit(yyscanner, OP_LE, NULL);
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
         $$.type = EXPRESSION_TYPE_BOOLEAN;
       }
     | primary_expression _GE_ primary_expression
       {
-        if (CHECK_TYPE_NO_CLEANUP($1, EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP($1, EXPRESSION_TYPE_DOUBLE))
+        if ($1.type != $3.type)
         {
-          CLEANUP(">=", $1);
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for >= operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GED, NULL);
         }
-        if (CHECK_TYPE_NO_CLEANUP($3, EXPRESSION_TYPE_INTEGER) &&
-            CHECK_TYPE_NO_CLEANUP($3, EXPRESSION_TYPE_DOUBLE))
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
         {
-          CLEANUP(">=", $3);
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GE, NULL);
+        }
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_GED, NULL);
+        }
+        else
+        {
+          CLEANUP(">=", $1);
         }
-        TYPE_INEQUALITY($1, $3, ">=")
 
-        yr_parser_emit(yyscanner, OP_GE, NULL);
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
         $$.type = EXPRESSION_TYPE_BOOLEAN;
       }
@@ -1343,23 +1486,54 @@ expression
       {
         if ($1.type != $3.type)
         {
-          yr_compiler_set_error_extra_info(
-              compiler, "mismatching types for == operator");
-          compiler->last_result = ERROR_WRONG_TYPE;
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for == operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_EQD, NULL);
         }
         else if ($1.type == EXPRESSION_TYPE_STRING)
         {
-          compiler->last_result = yr_parser_emit(
-              yyscanner,
-              OP_STR_EQ,
-              NULL);
+          compiler->last_result = yr_parser_emit(yyscanner, OP_STR_EQ, NULL);
+        }
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_EQ, NULL);
+        }
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_EQD, NULL);
         }
         else
         {
-          compiler->last_result = yr_parser_emit(
-              yyscanner,
-              OP_EQ,
-              NULL);
+          CLEANUP("==", $1);
         }
 
         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
@@ -1397,23 +1571,54 @@ expression
       {
         if ($1.type != $3.type)
         {
-          yr_compiler_set_error_extra_info(
-              compiler, "mismatching types for != operator");
-          compiler->last_result = ERROR_WRONG_TYPE;
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                2,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            compiler->last_result = yr_parser_emit_with_arg(
+                yyscanner,
+                OP_ITD,
+                1,
+                NULL);
+            ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for != operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
+
+          compiler->last_result = yr_parser_emit(yyscanner, OP_NEQD, NULL);
         }
         else if ($1.type == EXPRESSION_TYPE_STRING)
         {
-          compiler->last_result = yr_parser_emit(
-              yyscanner,
-              OP_STR_NEQ,
-              NULL);
+          compiler->last_result = yr_parser_emit(yyscanner, OP_STR_NEQ, NULL);
+        }
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_NEQ, NULL);
+        }
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
+        {
+          compiler->last_result = yr_parser_emit(yyscanner, OP_NEQD, NULL);
         }
         else
         {
-          compiler->last_result = yr_parser_emit(
-              yyscanner,
-              OP_NEQ,
-              NULL);
+          CLEANUP("!=", $1);
         }
 
         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
@@ -1698,7 +1903,7 @@ primary_expression
               break;
             case OBJECT_TYPE_DOUBLE:
               $$.type = EXPRESSION_TYPE_DOUBLE;
-              $$.value.integer = UNDEFINED;
+              $$.value.double_ = UNDEFINED;
               break;
             case OBJECT_TYPE_STRING:
               $$.type = EXPRESSION_TYPE_STRING;
@@ -1717,43 +1922,187 @@ primary_expression
       }
     | primary_expression '+' primary_expression
       {
-        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "+");
-        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "+");
-
-        yr_parser_emit(yyscanner, OP_ADD, NULL);
+        if ($1.type != $3.type)
+        {
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 2, NULL);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 1, NULL);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for + operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
 
-        $$.type = EXPRESSION_TYPE_INTEGER;
-        $$.value.integer = OPERATION(+, $1.value.integer, $3.value.integer);
+          yr_parser_emit(yyscanner, OP_ADD_DBL, NULL);
+          $$.type = EXPRESSION_TYPE_DOUBLE;
+          $$.value.double_ = OPERATION(+, $1.value.double_, $3.value.double_);
+        }
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
+        {
+          yr_parser_emit(yyscanner, OP_ADD, NULL);
+          $$.type = EXPRESSION_TYPE_INTEGER;
+          $$.value.integer = OPERATION(+, $1.value.integer, $3.value.integer);
+        }
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
+        {
+          yr_parser_emit(yyscanner, OP_ADD_DBL, NULL);
+          $$.type = EXPRESSION_TYPE_DOUBLE;
+          $$.value.double_ = OPERATION(+, $1.value.double_, $3.value.double_);
+        }
+        else
+        {
+          CLEANUP("+", $1);
+        }
       }
     | primary_expression '-' primary_expression
       {
-        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "-");
-        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "-");
-
-        yr_parser_emit(yyscanner, OP_SUB, NULL);
+        if ($1.type != $3.type)
+        {
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 2, NULL);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 1, NULL);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for - operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
 
-        $$.type = EXPRESSION_TYPE_INTEGER;
-        $$.value.integer = OPERATION(-, $1.value.integer, $3.value.integer);
+          yr_parser_emit(yyscanner, OP_SUB_DBL, NULL);
+          $$.type = EXPRESSION_TYPE_DOUBLE;
+          $$.value.double_ = OPERATION(-, $1.value.double_, $3.value.double_);
+        }
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
+        {
+          yr_parser_emit(yyscanner, OP_SUB, NULL);
+          $$.type = EXPRESSION_TYPE_INTEGER;
+          $$.value.integer = OPERATION(-, $1.value.integer, $3.value.integer);
+        }
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
+        {
+          yr_parser_emit(yyscanner, OP_SUB_DBL, NULL);
+          $$.type = EXPRESSION_TYPE_DOUBLE;
+          $$.value.double_ = OPERATION(-, $1.value.double_, $3.value.double_);
+        }
+        else
+        {
+          CLEANUP("-", $1);
+        }
       }
     | primary_expression '*' primary_expression
       {
-        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "*");
-        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "*");
-
-        yr_parser_emit(yyscanner, OP_MUL, NULL);
+        if ($1.type != $3.type)
+        {
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 2, NULL);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 1, NULL);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for * operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
 
-        $$.type = EXPRESSION_TYPE_INTEGER;
-        $$.value.integer = OPERATION(*, $1.value.integer, $3.value.integer);
+          yr_parser_emit(yyscanner, OP_MUL_DBL, NULL);
+          $$.type = EXPRESSION_TYPE_DOUBLE;
+          $$.value.double_ = OPERATION(*, $1.value.double_, $3.value.double_);
+        }
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
+        {
+          yr_parser_emit(yyscanner, OP_MUL, NULL);
+          $$.type = EXPRESSION_TYPE_INTEGER;
+          $$.value.integer = OPERATION(*, $1.value.integer, $3.value.integer);
+        }
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
+        {
+          yr_parser_emit(yyscanner, OP_MUL_DBL, NULL);
+          $$.type = EXPRESSION_TYPE_DOUBLE;
+          $$.value.double_ = OPERATION(*, $1.value.double_, $3.value.double_);
+        }
+        else
+        {
+          CLEANUP("*", $1);
+        }
       }
     | primary_expression '\\' primary_expression
       {
-        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "\\");
-        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "\\");
-
-        yr_parser_emit(yyscanner, OP_DIV, NULL);
+        if ($1.type != $3.type)
+        {
+          if ($1.type == EXPRESSION_TYPE_INTEGER &&
+              $3.type == EXPRESSION_TYPE_DOUBLE)
+          {
+            // Cast left side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 2, NULL);
+          }
+          else if ($1.type == EXPRESSION_TYPE_DOUBLE &&
+                   $3.type == EXPRESSION_TYPE_INTEGER)
+          {
+            // Cast right side to double.
+            yr_parser_emit_with_arg(yyscanner, OP_ITD, 1, NULL);
+          }
+          else
+          {
+            yr_compiler_set_error_extra_info(
+                compiler, "mismatching types for \\ operator");
+            compiler->last_result = ERROR_WRONG_TYPE;
+            yyerror(yyscanner, compiler, NULL);
+            YYERROR;
+          }
 
-        $$.type = EXPRESSION_TYPE_INTEGER;
-        $$.value.integer = OPERATION(/, $1.value.integer, $3.value.integer);
+          yr_parser_emit(yyscanner, OP_DIV_DBL, NULL);
+          $$.type = EXPRESSION_TYPE_DOUBLE;
+          $$.value.double_ = OPERATION(/, $1.value.double_, $3.value.double_);
+        }
+        else if ($1.type == EXPRESSION_TYPE_INTEGER)
+        {
+          yr_parser_emit(yyscanner, OP_DIV, NULL);
+          $$.type = EXPRESSION_TYPE_INTEGER;
+          $$.value.integer = OPERATION(*, $1.value.integer, $3.value.integer);
+        }
+        else if ($1.type == EXPRESSION_TYPE_DOUBLE)
+        {
+          yr_parser_emit(yyscanner, OP_DIV_DBL, NULL);
+          $$.type = EXPRESSION_TYPE_DOUBLE;
+          $$.value.double_ = OPERATION(/, $1.value.double_, $3.value.double_);
+        }
+        else
+        {
+          CLEANUP("\\", $1);
+        }
       }
     | primary_expression '%' primary_expression
       {
diff --git a/libyara/include/yara/exec.h b/libyara/include/yara/exec.h
index 37ee034..7799a6f 100644
--- a/libyara/include/yara/exec.h
+++ b/libyara/include/yara/exec.h
@@ -80,6 +80,17 @@ limitations under the License.
 #define OP_MATCHES        50
 #define OP_IMPORT         51
 #define OP_LOOKUP_DICT    52
+#define OP_ITD            53
+#define OP_LTD            54
+#define OP_GTD            55
+#define OP_LED            56
+#define OP_GED            57
+#define OP_EQD            58
+#define OP_NEQD           59
+#define OP_ADD_DBL        60
+#define OP_SUB_DBL        61
+#define OP_MUL_DBL        62
+#define OP_DIV_DBL        63
 
 
 #define OP_INT            100

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list