var_t * exp_eval(exp_t *exp, var_t *mailspec) { if (exp == NULL) { log_debug("exp_eval: expression is null"); return NULL; } switch (exp->ex_type) { case EX_PARENTHESES: return exp_eval(exp->ex_data, mailspec); case EX_CONSTANT: return exp->ex_data; case EX_LIST: return exp_eval_list(exp, mailspec); case EX_SYMBOL: return acl_symbol_get(mailspec, exp->ex_data); case EX_FUNCTION: return exp_eval_function(exp, mailspec); case EX_OPERATION: return exp_eval_operation(exp, mailspec); case EX_VARIABLE: return exp_eval_variable(exp, mailspec); case EX_MACRO: return exp_eval_macro(exp, mailspec); case EX_TERNARY_COND: return exp_eval_ternary_condition(exp, mailspec); default: log_error("exp_eval: bad type"); } return NULL; }
static var_t * exp_assign(exp_t *left, exp_t *right, var_t *mailspec) { var_t *value; char *name; if (left->ex_type != EX_VARIABLE) { log_error("exp_assign: left expression is faulty"); return NULL; } name = left->ex_data; /* * Evaluate expression */ value = exp_eval(right, mailspec); if (value == NULL) { log_error("exp_eval_variables: exp_eval failed"); return NULL; } if (acl_variable_assign(mailspec, name, value)) { log_error("exp_eval_variable: acl_variable_assign failed"); return NULL; } return value; }
int evaluate(char *exp, bool used[], int vals[]) { int i = 0, res = 0, opcount = 0, varcount = 0; char op; while (exp[i]) { if (isalpha(exp[i])) { varcount++; if (varcount == 1) { res = vals[exp[i] - DIFF]; if (opcount == 1) { res = unary_exp_eval(vals[exp[i] - DIFF], op); } } else if (varcount > 1) { res = exp_eval(res, vals[exp[i] - DIFF], op); } opcount = 0; used[exp[i] - DIFF] = true; } else if (isoperator(exp[i])) { opcount++; if (opcount == 1 || (opcount == 3 && exp[i] != exp[i-1])) { op = exp[i]; } } i++; } return res; }
static var_t * exp_eval_ternary_condition(exp_t *exp, var_t *mailspec) { exp_ternary_condition_t *etc = exp->ex_data; var_t *v = NULL; int result; v = exp_eval(etc->etc_condition, mailspec); if (v == NULL) { log_error("exp_eval_ternary_condition: evaluation failed"); return NULL; } result = var_true(v); exp_free(v); if (result) { return exp_eval(etc->etc_true, mailspec); } return exp_eval(etc->etc_false, mailspec); }
acl_action_type_t pipe_action(milter_stage_t stage, char *stagename, var_t *mailspec, void *data, int depth) { exp_t *exp = data; var_t *v; char *dest; char *message; int size; acl_action_type_t a; v = exp_eval(exp, mailspec); if (v == NULL) { log_error("pipe_exec: exp_eval failed"); return ACL_ERROR; } if (v->v_type != VT_STRING) { log_error("pipe_exec: bad expression in mail.acl"); return ACL_ERROR; } dest = v->v_data; log_message(LOG_ERR, mailspec, "pipe_exec: %s", dest); size = milter_message(mailspec, &message); if (size == -1) { log_error("pipe_exec: milter_message failed"); return ACL_ERROR; } if (strncmp(dest, "inet:", 5) == 0 || strncmp(dest, "unix:", 5) == 0) { a = pipe_socket(dest, message, size); } else { a = pipe_exec(dest, message, size); } free(message); return a; }
static var_t * exp_eval_list(exp_t *exp, var_t *mailspec) { ll_t *exp_list = exp->ex_data; ll_entry_t *pos; exp_t *exp_item; var_t *var_item, *var_list = NULL; var_list = vlist_create(NULL, VF_EXP_FREE); if (var_list == NULL) { log_sys_error("exp_eval_list: malloc"); goto error; } pos = LL_START(exp_list); while ((exp_item = ll_next(exp_list, &pos))) { var_item = exp_eval(exp_item, mailspec); if (vlist_append(var_list, var_item)) { log_sys_error("exp_eval_list: malloc"); goto error; } } return var_list; error: if (var_list) { var_delete(var_list); } return NULL; }
int exp_is_true(exp_t *exp, var_t *mailspec) { var_t *v; int r; if (exp == NULL) { return 1; } v = exp_eval(exp, mailspec); if (v == NULL) { log_notice("exp_is_true: evaluation failed"); return -1; } r = var_true(v); exp_free(v); return r; }
static var_t * exp_bool(var_t *mailspec, int op, exp_t *left_exp, exp_t *right_exp) { int known_value, left_known, right_known, result; int left_true = 0; int right_true = 0; var_t *left = NULL; var_t *right = NULL; if (op != OR && op != AND) { log_error("exp_bool: bad operation"); return NULL; } if (left_exp == NULL || right_exp == NULL) { log_error("exp_bool: operand is NULL"); return NULL; } // Evaluate left operand left = exp_eval(left_exp, mailspec); if (left == NULL) { log_error("exp_bool: exp_eval for lefthand operator failed"); return NULL; } left_known = left->v_data != NULL; if (left_known) { left_true = var_true(left); } // Short-Circuit Operator (like Perl) if (op == OR && left_known && left_true) { return left; } exp_free(left); // AND operation with left value known and false. if (op == AND && left_known && !left_true) { return &exp_false; } // Evaluate right operand right = exp_eval(right_exp, mailspec); if (right == NULL) { log_error("exp_bool: exp_eval for righthand operator failed"); return NULL; } right_known = right->v_data != NULL; if (right_known) { right_true = var_true(right); } // Short-Circuit Operator (like Perl) if (op == OR && !left_true) { return right; } exp_free(right); // Both sides are unknown if (!left_known && !right_known) { return &exp_empty; } // One side is unknown if (!left_known || !right_known) { known_value = left_known ? left_true: right_true; if (op == AND && !known_value) { return &exp_false; } // This case should be handled by the shortcut logic above! if (op == OR && known_value) { log_error("exp_bool: logic error"); return NULL; } return &exp_empty; } // Both sides are known if (op == AND) { result = left_true && right_true; } else { result = left_true || right_true; } if (result) { return &exp_true; } return &exp_false; }
static var_t * exp_eval_function(exp_t *exp, var_t *mailspec) { exp_function_t *ef = exp->ex_data; acl_function_t *af; var_t *args = NULL; ll_t *single = NULL; var_t *v = NULL; af = acl_function_lookup(ef->ef_name); if (af == NULL) { log_error("exp_eval_function: unknown function \"%s\"", ef->ef_name); goto error; } /* * Function has arguments */ if (ef->ef_args) { args = exp_eval(ef->ef_args, mailspec); if (args == NULL) { log_error("exp_eval_function: exp_eval failed"); goto error; } /* * Convert single argument into list. */ if (args->v_type != VT_LIST) { single = ll_create(); if (single == NULL) { log_error("exp_eval_function: ll_create failed"); goto error; } if (LL_INSERT(single, args) == -1) { log_error("exp_eval_function: LL_INSERT failed"); goto error; } } } else { /* * Function has no arguments -> empty list */ single = ll_create(); if (single == NULL) { log_error("exp_eval_function: ll_create failed"); goto error; } } if (af->af_type == AF_SIMPLE) { v = exp_eval_function_simple(ef->ef_name, af, single ? single : args->v_data); } else { v = exp_eval_function_complex(ef->ef_name, af, single ? single : args->v_data); } if (v == NULL) { log_error("exp_eval_function: function \"%s\" failed", ef->ef_name); goto error; } error: if (single) { ll_delete(single, NULL); } if (args) { exp_free(args); } return v; }
void exp_test(int n) { // exp_is_true TEST_ASSERT(!exp_is_true(exp_test_int_0, NULL)); TEST_ASSERT(exp_is_true(exp_test_int_1, NULL)); TEST_ASSERT(exp_is_true(exp_test_int_2, NULL)); TEST_ASSERT(exp_is_true(exp_test_int_3, NULL)); TEST_ASSERT(!exp_is_true(exp_test_float_0, NULL)); TEST_ASSERT(exp_is_true(exp_test_float_1, NULL)); TEST_ASSERT(exp_is_true(exp_test_float_2, NULL)); TEST_ASSERT(exp_is_true(exp_test_float_3, NULL)); TEST_ASSERT(!exp_is_true(exp_test_str_0, NULL)); TEST_ASSERT(exp_is_true(exp_test_str_1, NULL)); TEST_ASSERT(exp_is_true(exp_test_str_2, NULL)); TEST_ASSERT(exp_is_true(exp_test_str_3, NULL)); TEST_ASSERT(!exp_is_true(exp_test_null, NULL)); TEST_ASSERT(!exp_is_true(exp_test_addr_0, NULL)); TEST_ASSERT(!exp_is_true(exp_test_addr_1, NULL)); TEST_ASSERT(exp_is_true(exp_test_addr_2, NULL)); TEST_ASSERT(exp_is_true(exp_test_addr_3, NULL)); TEST_ASSERT(exp_is_true(exp_test_addr_4, NULL)); // Not TEST_ASSERT(exp_eval(exp_operation('!', exp_test_int_0, NULL), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_int_1, NULL), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_float_0, NULL), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_float_1, NULL), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_str_0, NULL), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_str_1, NULL), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_addr_2, NULL), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_addr_3, NULL), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_addr_0, NULL), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_addr_1, NULL), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('!', exp_test_null, NULL), NULL) == EXP_EMPTY); // AND TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_int_0, exp_test_float_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_str_1, exp_test_float_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_str_0, exp_test_int_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_int_1, exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_null, exp_test_str_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_int_1, exp_test_null), NULL) == EXP_EMPTY); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_int_1, exp_test_addr_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_addr_0, exp_test_addr_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_addr_2, exp_test_addr_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_addr_3, exp_test_addr_4), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(AND, exp_test_null, exp_test_null), NULL) == EXP_EMPTY); // OR TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_int_0, exp_test_float_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_str_1, exp_test_float_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_str_0, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_int_1, exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_null, exp_test_str_0), NULL) == EXP_EMPTY); TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_int_1, exp_test_null), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_addr_0, exp_test_addr_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_addr_1, exp_test_str_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_addr_0, exp_test_addr_4), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(OR, exp_test_null, exp_test_null), NULL) == EXP_EMPTY); // < TEST_ASSERT(exp_eval(exp_operation('<', exp_test_int_0, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_int_1, exp_test_int_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_float_0, exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_float_1, exp_test_float_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_int_1, exp_test_float_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_int_1, exp_test_int_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_int_2, exp_test_int_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_float_1, exp_test_float_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_float_2, exp_test_float_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_float_3, exp_test_int_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_int_1, exp_test_float_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_addr_0, exp_test_addr_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_addr_1, exp_test_addr_4), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_addr_2, exp_test_addr_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_addr_0, exp_test_addr_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('<', exp_test_addr_1, exp_test_addr_1), NULL) == EXP_FALSE); // > TEST_ASSERT(exp_eval(exp_operation('>', exp_test_int_1, exp_test_int_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_int_2, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_float_1, exp_test_float_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_float_2, exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_float_3, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_int_1, exp_test_int_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_int_1, exp_test_int_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_float_1, exp_test_float_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_float_1, exp_test_float_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_int_1, exp_test_float_3), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_int_1, exp_test_float_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_addr_2, exp_test_addr_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_addr_4, exp_test_addr_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_addr_3, exp_test_addr_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_addr_0, exp_test_addr_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation('>', exp_test_addr_1, exp_test_addr_1), NULL) == EXP_FALSE); // LE TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_int_0, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_int_1, exp_test_int_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_float_0, exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_float_1, exp_test_float_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_int_1, exp_test_float_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_int_1, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_float_1, exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_int_1, exp_test_float_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_int_2, exp_test_int_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_float_2, exp_test_float_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_float_3, exp_test_int_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_addr_0, exp_test_addr_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_addr_1, exp_test_addr_4), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_addr_2, exp_test_addr_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_addr_0, exp_test_addr_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(LE, exp_test_addr_1, exp_test_addr_1), NULL) == EXP_TRUE); // GE TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_int_1, exp_test_int_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_int_2, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_float_1, exp_test_float_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_float_2, exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_float_3, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_int_1, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_float_1, exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_float_2, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_int_1, exp_test_int_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_float_1, exp_test_float_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_int_1, exp_test_float_3), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_addr_2, exp_test_addr_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_addr_4, exp_test_addr_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_addr_3, exp_test_addr_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_addr_0, exp_test_addr_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(GE, exp_test_addr_1, exp_test_addr_1), NULL) == EXP_TRUE); // EQ TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_int_0, exp_test_int_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_int_1, exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_float_0, exp_test_float_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_float_1, exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_str_0, exp_test_str_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_str_3, exp_test_str_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_int_1, exp_test_str_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_float_3, exp_test_str_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_int_1, exp_test_int_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_float_1, exp_test_float_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_str_1, exp_test_str_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_int_1, exp_test_float_3), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_float_1, exp_test_str_3), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_int_3, exp_test_str_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_addr_2, exp_test_addr_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_addr_4, exp_test_addr_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_addr_3, exp_test_addr_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_addr_0, exp_test_addr_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_test_addr_1, exp_test_addr_1), NULL) == EXP_TRUE); // NE TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_int_0, exp_test_int_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_int_1, exp_test_int_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_float_0, exp_test_float_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_float_1, exp_test_float_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_str_0, exp_test_str_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_str_3, exp_test_str_3), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_int_1, exp_test_str_1), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_float_3, exp_test_str_2), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_int_1, exp_test_int_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_float_1, exp_test_float_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_str_1, exp_test_str_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_int_1, exp_test_float_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_float_1, exp_test_str_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_int_3, exp_test_str_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_addr_2, exp_test_addr_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_addr_4, exp_test_addr_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_addr_3, exp_test_addr_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_addr_0, exp_test_addr_0), NULL) == EXP_FALSE); TEST_ASSERT(exp_eval(exp_operation(NE, exp_test_addr_1, exp_test_addr_1), NULL) == EXP_FALSE); // + TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_int_0, exp_test_int_1), exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_int_1, exp_test_int_2), exp_test_int_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_float_0, exp_test_float_1), exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_float_1, exp_test_float_2), exp_test_float_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_str_0, exp_test_str_1), exp_test_str_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_str_1, exp_test_str_2), exp_test_str_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_int_1, exp_test_float_1), exp_test_float_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_int_1, exp_test_str_2), exp_test_str_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_int_1, exp_test_str_0), exp_test_str_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('+', exp_test_float_3, exp_test_str_0), exp_test_str_2), NULL) == EXP_TRUE); // - TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('-', exp_test_int_1, exp_test_int_0), exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('-', exp_test_int_3, exp_test_int_1), exp_test_int_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('-', exp_test_float_1, exp_test_float_0), exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('-', exp_test_float_3, exp_test_float_1), exp_test_float_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('-', exp_test_float_3, exp_test_int_1), exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('-', exp_test_int_1, exp_test_float_1), exp_test_float_1), NULL) == EXP_TRUE); // * TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('*', exp_test_int_1, exp_test_int_0), exp_test_int_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('*', exp_test_int_2, exp_test_int_1), exp_test_int_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('*', exp_test_float_1, exp_test_float_0), exp_test_float_0), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('*', exp_test_float_2, exp_test_float_3), exp_test_float_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('*', exp_test_float_1, exp_test_int_2), exp_test_float_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('*', exp_test_int_1, exp_test_float_3), exp_test_float_3), NULL) == EXP_TRUE); // / TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('/', exp_test_int_2, exp_test_int_1), exp_test_int_2), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('/', exp_test_int_3, exp_test_int_2), exp_test_int_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('/', exp_test_float_3, exp_test_float_2), exp_test_float_3), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('/', exp_test_float_2, exp_test_int_2), exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('/', exp_test_float_3, exp_test_int_3), exp_test_float_1), NULL) == EXP_TRUE); TEST_ASSERT(exp_eval(exp_operation(EQ, exp_operation('/', exp_test_int_3, exp_test_float_3), exp_test_int_2), NULL) == EXP_TRUE); return; }
var_t * exp_eval_operation(exp_t *exp, var_t *mailspec) { var_t *left = NULL, *right = NULL, *copy; exp_operation_t *eo = exp->ex_data; var_t *result = NULL; var_type_t type; /* * Variable assigment */ if (eo->eo_operator == '=') { return exp_assign(eo->eo_operand[0], eo->eo_operand[1], mailspec); } /* * isset operator */ if (eo->eo_operator == IS_SET) { return exp_isset(mailspec, eo->eo_operand[0]); } /* * Do not load unneccessary symbols in boolean operations */ if (eo->eo_operator == AND || eo->eo_operator == OR) { result = exp_bool(mailspec, eo->eo_operator, eo->eo_operand[0], eo->eo_operand[1]); goto exit; } /* * Load left operand */ left = exp_eval(eo->eo_operand[0], mailspec); /* * ! operator */ if (eo->eo_operator == '!') { return exp_not(left); } /* * Hack: IS_NULL operator */ if (eo->eo_operator == IS_NULL) { result = exp_is_null(left); goto exit; } /* * Evaluate right operand */ if (eo->eo_operand[1]) { right = exp_eval(eo->eo_operand[1], mailspec); } switch(eo->eo_operator) { // Comparator case '<': case '>': case LE: case GE: case EQ: case NE: result = exp_compare(eo->eo_operator, left, right); goto exit; // Regex case '~': case NR: result = exp_eval_regex(eo->eo_operator, left, right); goto exit; // In case IN: result = exp_eval_in(left, right); goto exit; // Address prefix operator case '/': if (left == NULL || right == NULL) { break; } if (!(left->v_type == VT_ADDR && right->v_type == VT_INT)) { break; } result = exp_addr_prefix(left, right); goto exit; default: break; } // Math operators need left and right to be set if (left == NULL || right == NULL) { result = EXP_EMPTY; goto exit; } // Make sure we work with the same types if (left->v_type != right->v_type) { /* * The biggest type has precedence (see exp.h) * STRING > FLOAT > INT */ type = VAR_MAX_TYPE(left, right); if (type == left->v_type) { copy = var_cast_copy(type, right); } else { copy = var_cast_copy(type, left); } if (copy == NULL) { log_error("exp_eval_operation: var_cast_copy " "failed"); goto exit; } if (type == left->v_type) { exp_free(right); right = copy; right->v_flags |= VF_EXP_FREE; } else { exp_free(left); left = copy; left->v_flags |= VF_EXP_FREE; } } switch (left->v_type) { case VT_INT: result = exp_math_int(eo->eo_operator, left, right); break; case VT_FLOAT: result = exp_math_float(eo->eo_operator, left, right); break; case VT_STRING: result = exp_math_string(eo->eo_operator, left, right); break; default: log_error("exp_eval_operation: bad type"); goto exit; } exit: if (left) { exp_free(left); } if (right) { exp_free(right); } return result; }
acl_action_type_t msgmod(milter_stage_t stage, char *stagename, var_t *mailspec, void *data, int depth) { msgmod_t *mm = data; void *ctx; acl_action_type_t action = ACL_ERROR; var_t **args = NULL; int argc; int size; var_t *v, *copy; int i; exp_t *exp; ll_t *ll; ll_entry_t *pos; /* * Get milter ctx pointer */ ctx = vtable_get(mailspec, "milter_ctx"); if (ctx == NULL) { log_error("msgmod: ctx not set"); goto error; } /* * Evaluate arguments */ argc = mm->mm_args->ll_size; size = (argc + 1) * sizeof (var_t *); args = (var_t **) malloc(size); if (args == NULL) { log_sys_error("msgmod: malloc"); goto error; } memset(args, 0, size); ll = mm->mm_args; pos = LL_START(ll); for (i = 0; i < argc; ++i) { exp = ll_next(ll, &pos); if (exp == NULL) { log_die(EX_SOFTWARE, "msgmod: empty argument"); } v = exp_eval(exp, mailspec); if (v == NULL) { log_error("msgmod: exp_eval failed"); goto error; } // Cast all aruments to VT_STRING if (v->v_type != VT_STRING) { copy = var_cast_copy(VT_STRING, v); if (copy == NULL) { log_error("msgmod: var_cast_copy failed"); goto error; } exp_free(v); /* * args are freed using exp_free. Set VF_EXP_FREE to * free copy. */ copy->v_flags |= VF_EXP_FREE; v = copy; } args[i] = v; } if (mm->mm_callback(ctx, argc, args)) { log_error("msgmod: mm_callback failed"); goto error; } action = ACL_NONE; error: /* * Free args */ for (i = 0; args[i]; ++i) { exp_free(args[i]); } if (args) { free(args); } return action; }