Print this page
11506 smatch resync

@@ -77,11 +77,11 @@
         char buf[1024] = "";
         bool found = false;
         int i, j;
 
         for (i = 0, j = 0; str[i] != '\0' && j != sizeof(buf); i++, j++) {
-                if (str[i] != '\n') {
+                if (str[i] != '\r' && str[i] != '\n') {
                         buf[j] = str[i];
                         continue;
                 }
 
                 found = true;

@@ -250,12 +250,12 @@
         free_string(fn);
 }
 
 void sql_insert_function_ptr(const char *fn, const char *struct_name)
 {
-        sql_insert(function_ptr, "'%s', '%s', '%s', 0", get_base_file(), fn,
-                   struct_name);
+        sql_insert_or_ignore(function_ptr, "'%s', '%s', '%s', 0",
+                             get_base_file(), fn, struct_name);
 }
 
 void sql_insert_return_implies(int type, int param, const char *key, const char *value)
 {
         sql_insert_or_ignore(return_implies, "'%s', '%s', %lu, %d, %d, %d, '%s', '%s'",

@@ -329,11 +329,11 @@
 void sql_save_constraint(const char *con)
 {
         if (!option_info)
                 return;
 
-        sm_msg("SQL: insert or ignore into constraints (str) values('%s');", con);
+        sm_msg("SQL: insert or ignore into constraints (str) values('%s');", escape_newlines(con));
 }
 
 void sql_save_constraint_required(const char *data, int op, const char *limit)
 {
         sql_insert_or_ignore(constraints_required, "'%s', '%s', '%s'", data, show_special(op), limit);

@@ -370,15 +370,10 @@
 {
         sql_insert(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'",
                    tag, get_filename(), get_function(), get_lineno(), left_name, right_name);
 }
 
-void sql_insert_mtag_data(mtag_t tag, const char *var, int offset, int type, const char *value)
-{
-        sql_insert(mtag_data, "%lld, '%s', %d, %d, '%s'", tag, var, offset, type, value);
-}
-
 void sql_insert_mtag_map(mtag_t tag, int offset, mtag_t container)
 {
         sql_insert(mtag_map, "%lld, %d, %lld", tag, offset, container);
 }
 

@@ -748,58 +743,101 @@
         if (offset != -1)
                 snprintf(buf, sizeof(buf), "(-%d)", offset);
         return buf;
 }
 
+int is_recursive_member(const char *name)
+{
+        char buf[256];
+        const char *p, *next;
+        int size;
+
+        p = strchr(name, '>');
+        if (!p)
+                return 0;
+        p++;
+        while (true) {
+                next = strchr(p, '>');
+                if (!next)
+                        return 0;
+                next++;
+
+                size = next - p;
+                if (size >= sizeof(buf))
+                        return 0;
+                memcpy(buf, p, size);
+                buf[size] = '\0';
+                if (strstr(next, buf))
+                        return 1;
+                p = next;
+        }
+}
+
 static void print_struct_members(struct expression *call, struct expression *expr, int param, int offset, struct stree *stree,
         void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
 {
         struct sm_state *sm;
+        const char *sm_name;
         char *name;
         struct symbol *sym;
         int len;
         char printed_name[256];
         int is_address = 0;
+        bool add_star;
         struct symbol *type;
 
         expr = strip_expr(expr);
         if (!expr)
                 return;
+        type = get_type(expr);
+        if (type && type_bits(type) < type_bits(&ulong_ctype))
+                return;
+
         if (expr->type == EXPR_PREOP && expr->op == '&') {
                 expr = strip_expr(expr->unop);
                 is_address = 1;
         }
 
-        type = get_type(expr);
-        if (type && type_bits(type) < type_bits(&ulong_ctype))
-                return;
-
         name = expr_to_var_sym(expr, &sym);
         if (!name || !sym)
                 goto free;
 
         len = strlen(name);
         FOR_EACH_SM(stree, sm) {
                 if (sm->sym != sym)
                         continue;
-                if (strcmp(name, sm->name) == 0) {
+                sm_name = sm->name;
+                add_star = false;
+                if (sm_name[0] == '*') {
+                        add_star = true;
+                        sm_name++;
+                }
+                // FIXME: simplify?
+                if (!add_star && strcmp(name, sm_name) == 0) {
                         if (is_address)
                                 snprintf(printed_name, sizeof(printed_name), "*$%s", show_offset(offset));
                         else /* these are already handled. fixme: handle them here */
                                 continue;
-                } else if (sm->name[0] == '*' && strcmp(name, sm->name + 1) == 0) {
-                        snprintf(printed_name, sizeof(printed_name), "*$%s", show_offset(offset));
-                } else if (strncmp(name, sm->name, len) == 0) {
-                        if (isalnum(sm->name[len]))
+                } else if (add_star && strcmp(name, sm_name) == 0) {
+                        snprintf(printed_name, sizeof(printed_name), "%s*$%s",
+                                 is_address ? "*" : "", show_offset(offset));
+                } else if (strncmp(name, sm_name, len) == 0) {
+                        if (sm_name[len] != '.' && sm_name[len] != '-')
                                 continue;
                         if (is_address)
-                                snprintf(printed_name, sizeof(printed_name), "$%s->%s", show_offset(offset), sm->name + len + 1);
+                                snprintf(printed_name, sizeof(printed_name),
+                                         "%s$%s->%s", add_star ? "*" : "",
+                                         show_offset(offset), sm_name + len + 1);
                         else
-                                snprintf(printed_name, sizeof(printed_name), "$%s%s", show_offset(offset), sm->name + len);
+                                snprintf(printed_name, sizeof(printed_name),
+                                         "%s$%s%s", add_star ? "*" : "",
+                                         show_offset(offset), sm_name + len);
                 } else {
                         continue;
                 }
+                if (is_recursive_member(printed_name))
+                        continue;
                 callback(call, param, printed_name, sm);
         } END_FOR_EACH_SM(sm);
 free:
         free_string(name);
 }

@@ -1007,13 +1045,12 @@
 static char *get_next_ptr_name(void)
 {
         char *ptr;
 
         FOR_EACH_PTR(ptr_names, ptr) {
-                if (list_has_string(ptr_names_done, ptr))
+                if (!insert_string(&ptr_names_done, ptr))
                         continue;
-                insert_string(&ptr_names_done, ptr);
                 return ptr;
         } END_FOR_EACH_PTR(ptr);
         return NULL;
 }
 

@@ -1222,57 +1259,101 @@
         info.sym = sym;
         sql_select_implies("function, type, parameter, key, value", &info,
                            call_implies_callbacks);
 }
 
-static void print_initializer_list(struct expression_list *expr_list,
-                struct symbol *struct_type)
+static char *get_return_compare_is_param(struct expression *expr)
 {
-        struct expression *expr;
-        struct symbol *base_type;
-        char struct_name[256];
+        char *var;
+        char buf[256];
+        int comparison;
+        int param;
 
-        FOR_EACH_PTR(expr_list, expr) {
-                if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
-                        print_initializer_list(expr->idx_expression->expr_list, struct_type);
-                        continue;
-                }
-                if (expr->type != EXPR_IDENTIFIER)
-                        continue;
-                if (!expr->expr_ident)
-                        continue;
-                if (!expr->ident_expression || !expr->ident_expression->symbol_name)
-                        continue;
-                base_type = get_type(expr->ident_expression);
-                if (!base_type || base_type->type != SYM_FN)
-                        continue;
-                snprintf(struct_name, sizeof(struct_name), "(struct %s)->%s",
-                         struct_type->ident->name, expr->expr_ident->name);
-                sql_insert_function_ptr(expr->ident_expression->symbol_name->name,
-                                        struct_name);
-        } END_FOR_EACH_PTR(expr);
+        param = get_param_num(expr);
+        if (param < 0)
+                return NULL;
+
+        var = expr_to_var(expr);
+        if (!var)
+                return NULL;
+        snprintf(buf, sizeof(buf), "%s orig", var);
+        comparison = get_comparison_strings(var, buf);
+        free_string(var);
+
+        if (!comparison)
+                return NULL;
+
+        snprintf(buf, sizeof(buf), "[%s$%d]", show_special(comparison), param);
+        return alloc_sname(buf);
 }
 
-static void global_variable(struct symbol *sym)
+static char *get_return_compare_str(struct expression *expr)
 {
-        struct symbol *struct_type;
+        char *compare_str;
 
-        if (!sym->ident)
-                return;
-        if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
-                return;
-        struct_type = get_base_type(sym);
-        if (!struct_type)
-                return;
-        if (struct_type->type == SYM_ARRAY) {
-                struct_type = get_base_type(struct_type);
-                if (!struct_type)
-                        return;
+        compare_str = get_return_compare_is_param(expr);
+        if (compare_str)
+                return compare_str;
+
+        compare_str = expr_lte_to_param(expr, -1);
+        if (compare_str)
+                return compare_str;
+
+        return expr_param_comparison(expr, -1);
+}
+
+static const char *get_return_ranges_str(struct expression *expr, struct range_list **rl_p)
+{
+        struct range_list *rl;
+        char *return_ranges;
+        sval_t sval;
+        char *compare_str;
+        char *math_str;
+        char buf[128];
+
+        *rl_p = NULL;
+
+        if (!expr)
+                return alloc_sname("");
+
+        if (get_implied_value(expr, &sval)) {
+                sval = sval_cast(cur_func_return_type(), sval);
+                *rl_p = alloc_rl(sval, sval);
+                return sval_to_str_or_err_ptr(sval);
         }
-        if (struct_type->type != SYM_STRUCT || !struct_type->ident)
-                return;
-        print_initializer_list(sym->initializer->expr_list, struct_type);
+
+        compare_str = expr_equal_to_param(expr, -1);
+        math_str = get_value_in_terms_of_parameter_math(expr);
+
+        if (get_implied_rl(expr, &rl) && !is_whole_rl(rl)) {
+                rl = cast_rl(cur_func_return_type(), rl);
+                return_ranges = show_rl(rl);
+        } else if (get_imaginary_absolute(expr, &rl)){
+                rl = cast_rl(cur_func_return_type(), rl);
+                return alloc_sname(show_rl(rl));
+        } else {
+                get_absolute_rl(expr, &rl);
+                rl = cast_rl(cur_func_return_type(), rl);
+                return_ranges = show_rl(rl);
+        }
+        *rl_p = rl;
+
+        if (compare_str) {
+                snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
+                return alloc_sname(buf);
+        }
+        if (math_str) {
+                snprintf(buf, sizeof(buf), "%s[%s]", return_ranges, math_str);
+                return alloc_sname(buf);
+        }
+        compare_str = get_return_compare_str(expr);
+        if (compare_str) {
+                snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
+                return alloc_sname(buf);
+        }
+
+        return return_ranges;
 }
 
 static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
 {
         sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", function_signature());

@@ -1280,44 +1361,37 @@
 
 static void call_return_state_hooks_conditional(struct expression *expr)
 {
         struct returned_state_callback *cb;
         struct range_list *rl;
-        char *return_ranges;
+        const char *return_ranges;
         int final_pass_orig = final_pass;
 
         __push_fake_cur_stree();
 
         final_pass = 0;
         __split_whole_condition(expr->conditional);
         final_pass = final_pass_orig;
 
-        if (get_implied_rl(expr->cond_true, &rl))
-                rl = cast_rl(cur_func_return_type(), rl);
-        else
-                rl = cast_rl(cur_func_return_type(), alloc_whole_rl(get_type(expr->cond_true)));
-        return_ranges = show_rl(rl);
+        return_ranges = get_return_ranges_str(expr->cond_true ?: expr->conditional, &rl);
+
         set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(rl));
 
         return_id++;
         FOR_EACH_PTR(returned_state_callbacks, cb) {
-                cb->callback(return_id, return_ranges, expr->cond_true);
+                cb->callback(return_id, (char *)return_ranges, expr->cond_true);
         } END_FOR_EACH_PTR(cb);
 
         __push_true_states();
         __use_false_states();
 
-        if (get_implied_rl(expr->cond_false, &rl))
-                rl = cast_rl(cur_func_return_type(), rl);
-        else
-                rl = cast_rl(cur_func_return_type(), alloc_whole_rl(get_type(expr->cond_false)));
-        return_ranges = show_rl(rl);
+        return_ranges = get_return_ranges_str(expr->cond_false, &rl);
         set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(rl));
 
         return_id++;
         FOR_EACH_PTR(returned_state_callbacks, cb) {
-                cb->callback(return_id, return_ranges, expr->cond_false);
+                cb->callback(return_id, (char *)return_ranges, expr->cond_false);
         } END_FOR_EACH_PTR(cb);
 
         __merge_true_states();
         __free_fake_cur_stree();
 }

@@ -1378,59 +1452,36 @@
         } END_FOR_EACH_PTR(tmp);
 
         return 0;
 }
 
-static char *get_return_compare_str(struct expression *expr)
-{
-        char *compare_str;
-        char *var;
-        char buf[256];
-        int comparison;
-        int param;
-
-        compare_str = expr_lte_to_param(expr, -1);
-        if (compare_str)
-                return compare_str;
-        param = get_param_num(expr);
-        if (param < 0)
-                return NULL;
-
-        var = expr_to_var(expr);
-        if (!var)
-                return NULL;
-        snprintf(buf, sizeof(buf), "%s orig", var);
-        comparison = get_comparison_strings(var, buf);
-        free_string(var);
-
-        if (!comparison)
-                return NULL;
-
-        snprintf(buf, sizeof(buf), "[%s$%d]", show_special(comparison), param);
-        return alloc_sname(buf);
-}
-
 static int split_possible_helper(struct sm_state *sm, struct expression *expr)
 {
         struct returned_state_callback *cb;
         struct range_list *rl;
         char *return_ranges;
         struct sm_state *tmp;
         int ret = 0;
         int nr_possible, nr_states;
-        char *compare_str = NULL;
+        char *compare_str;
         char buf[128];
         struct state_list *already_handled = NULL;
+        sval_t sval;
 
         if (!sm || !sm->merged)
                 return 0;
 
         if (too_many_possible(sm))
                 return 0;
 
         /* bail if it gets too complicated */
-        nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
+        nr_possible = 0;
+        FOR_EACH_PTR(sm->possible, tmp) {
+                if (tmp->merged)
+                        continue;
+                nr_possible++;
+        } END_FOR_EACH_PTR(tmp);
         nr_states = get_db_state_count();
         if (nr_states * nr_possible >= 2000)
                 return 0;
 
         FOR_EACH_PTR(sm->possible, tmp) {

@@ -1446,15 +1497,17 @@
                 overwrite_states_using_pool(sm, tmp);
 
                 rl = cast_rl(cur_func_return_type(), estate_rl(tmp->state));
                 return_ranges = show_rl(rl);
                 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(clone_rl(rl)));
+                if (!rl_to_sval(rl, &sval)) {
                 compare_str = get_return_compare_str(expr);
                 if (compare_str) {
                         snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
                         return_ranges = alloc_sname(buf);
                 }
+                }
 
                 return_id++;
                 FOR_EACH_PTR(returned_state_callbacks, cb) {
                         cb->callback(return_id, return_ranges, expr);
                 } END_FOR_EACH_PTR(cb);

@@ -1476,62 +1529,10 @@
 
         sm = get_sm_state_expr(SMATCH_EXTRA, expr);
         return split_possible_helper(sm, expr);
 }
 
-static const char *get_return_ranges_str(struct expression *expr, struct range_list **rl_p)
-{
-        struct range_list *rl;
-        char *return_ranges;
-        sval_t sval;
-        char *compare_str;
-        char *math_str;
-        char buf[128];
-
-        *rl_p = NULL;
-
-        if (!expr)
-                return alloc_sname("");
-
-        if (get_implied_value(expr, &sval)) {
-                sval = sval_cast(cur_func_return_type(), sval);
-                *rl_p = alloc_rl(sval, sval);
-                return sval_to_str(sval);
-        }
-
-        compare_str = expr_equal_to_param(expr, -1);
-        math_str = get_value_in_terms_of_parameter_math(expr);
-
-        if (get_implied_rl(expr, &rl)) {
-                rl = cast_rl(cur_func_return_type(), rl);
-                return_ranges = show_rl(rl);
-        } else if (get_imaginary_absolute(expr, &rl)){
-                rl = cast_rl(cur_func_return_type(), rl);
-                return alloc_sname(show_rl(rl));
-        } else {
-                rl = cast_rl(cur_func_return_type(), alloc_whole_rl(get_type(expr)));
-                return_ranges = show_rl(rl);
-        }
-        *rl_p = rl;
-
-        if (compare_str) {
-                snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
-                return alloc_sname(buf);
-        }
-        if (math_str) {
-                snprintf(buf, sizeof(buf), "%s[%s]", return_ranges, math_str);
-                return alloc_sname(buf);
-        }
-        compare_str = get_return_compare_str(expr);
-        if (compare_str) {
-                snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
-                return alloc_sname(buf);
-        }
-
-        return return_ranges;
-}
-
 static bool has_possible_negative(struct sm_state *sm)
 {
         struct sm_state *tmp;
 
         FOR_EACH_PTR(sm->possible, tmp) {

@@ -1566,10 +1567,11 @@
         struct returned_state_callback *cb;
         struct range_list *rl;
         const char *return_ranges;
         struct range_list *ret_rl;
         int undo;
+        bool has_zero;
 
         /* We're going to print the states 3 times */
         if (get_db_state_count() > 10000 / 3)
                 return 0;
 

@@ -1586,12 +1588,13 @@
         sm = get_sm_state_expr(SMATCH_EXTRA, expr);
         if (!sm)
                 return 0;
         if (!has_possible_negative(sm))
                 return 0;
+        has_zero = has_possible_zero_null(sm);
 
-        if (!assume(compare_expression(expr, '>', zero_expr())))
+        if (!assume(compare_expression(expr, has_zero ? '>' : SPECIAL_GTE, zero_expr())))
                 return 0;
 
         return_id++;
         return_ranges = get_return_ranges_str(expr, &ret_rl);
         set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));

@@ -1599,11 +1602,11 @@
                 cb->callback(return_id, (char *)return_ranges, expr);
         } END_FOR_EACH_PTR(cb);
 
         end_assume();
 
-        if (rl_has_sval(rl, sval_type_val(rl_type(rl), 0))) {
+        if (has_zero) {
                 undo = assume(compare_expression(expr, SPECIAL_EQUAL, zero_expr()));
 
                 return_id++;
                 return_ranges = get_return_ranges_str(expr, &ret_rl);
                 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));

@@ -1628,11 +1631,11 @@
                 end_assume();
 
         return 1;
 }
 
-static int call_return_state_hooks_split_null_non_null(struct expression *expr)
+static int call_return_state_hooks_split_null_non_null_zero(struct expression *expr)
 {
         struct returned_state_callback *cb;
         struct range_list *rl;
         struct range_list *nonnull_rl;
         sval_t null_sval;

@@ -1645,12 +1648,10 @@
 
         if (!expr || expr_equal_to_param(expr, -1))
                 return 0;
         if (expr->type == EXPR_CALL)
                 return 0;
-        if (!is_pointer(expr))
-                return 0;
 
         sm = get_sm_state_expr(SMATCH_EXTRA, expr);
         if (!sm)
                 return 0;
         if (ptr_list_size((struct ptr_list *)sm->possible) == 1)

@@ -1990,18 +1991,18 @@
         } else if (is_conditional(expr)) {
                 call_return_state_hooks_conditional(expr);
                 return;
         } else if (call_return_state_hooks_split_possible(expr)) {
                 return;
-        } else if (call_return_state_hooks_split_null_non_null(expr)) {
+        } else if (split_positive_from_negative(expr)) {
                 return;
+        } else if (call_return_state_hooks_split_null_non_null_zero(expr)) {
+                return;
         } else if (call_return_state_hooks_split_success_fail(expr)) {
                 return;
         } else if (splitable_function_call(expr)) {
                 return;
-        } else if (split_positive_from_negative(expr)) {
-                return;
         } else if (split_by_bool_param(expr)) {
         } else if (split_by_null_nonnull_param(expr)) {
                 return;
         }
 

@@ -2206,11 +2207,11 @@
 
         p += snprintf(p, 4096 - (p - buf), "insert or ignore into %s values (", table);
         for (i = 0; i < argc; i++) {
                 if (i)
                         p += snprintf(p, 4096 - (p - buf), ", ");
-                sqlite3_snprintf(sizeof(tmp), tmp, "%q", argv[i]);
+                sqlite3_snprintf(sizeof(tmp), tmp, "%q", escape_newlines(argv[i]));
                 p += snprintf(p, 4096 - (p - buf), "'%s'", tmp);
 
         }
         p += snprintf(p, 4096 - (p - buf), ");");
         if (p - buf > 4096)

@@ -2359,12 +2360,10 @@
 }
 
 void register_definition_db_callbacks(int id)
 {
         add_hook(&match_call_info, FUNCTION_CALL_HOOK);
-        add_hook(&global_variable, BASE_HOOK);
-        add_hook(&global_variable, DECLARATION_HOOK);
         add_split_return_callback(match_return_info);
         add_split_return_callback(print_returned_struct_members);
         add_hook(&call_return_state_hooks, RETURN_HOOK);
         add_hook(&match_end_func_info, END_FUNC_HOOK);
         add_hook(&match_after_func, AFTER_FUNC_HOOK);

@@ -2395,10 +2394,12 @@
         if (param == -1) {
                 const char *star = "";
 
                 if (expr->type != EXPR_ASSIGNMENT)
                         return NULL;
+                if (get_type(expr->left) == &int_ctype && strcmp(key, "$") != 0)
+                        return NULL;
                 name = expr_to_var_sym(expr->left, sym);
                 if (!name)
                         return NULL;
                 if (key[0] == '*') {
                         star = "*";

@@ -2425,10 +2426,11 @@
 
 char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym)
 {
         char buf[256];
         char *tmp;
+        bool add_star = false;
 
         if (!arg)
                 return NULL;
 
         arg = strip_expr(arg);

@@ -2448,23 +2450,29 @@
                         free_string(tmp);
                         return alloc_string(buf);
                 }
         }
 
+        if (key[0] == '*') {
+                add_star = true;
+                key++;
+        }
+
         if (arg->type == EXPR_PREOP && arg->op == '&') {
                 arg = strip_expr(arg->unop);
                 tmp = expr_to_var_sym(arg, sym);
                 if (!tmp)
                         return NULL;
-                snprintf(buf, sizeof(buf), "%s.%s", tmp, key + 3);
+                snprintf(buf, sizeof(buf), "%s%s.%s",
+                         add_star ? "*" : "", tmp, key + 3);
                 return alloc_string(buf);
         }
 
         tmp = expr_to_var_sym(arg, sym);
         if (!tmp)
                 return NULL;
-        snprintf(buf, sizeof(buf), "%s%s", tmp, key + 1);
+        snprintf(buf, sizeof(buf), "%s%s%s", add_star ? "*" : "", tmp, key + 1);
         free_string(tmp);
         return alloc_string(buf);
 }
 
 char *get_chunk_from_key(struct expression *arg, char *key, struct symbol **sym, struct var_sym_list **vsl)

@@ -2478,21 +2486,29 @@
 
 const char *state_name_to_param_name(const char *state_name, const char *param_name)
 {
         int name_len;
         static char buf[256];
+        bool add_star = false;
 
         name_len = strlen(param_name);
 
+        if (state_name[0] == '*') {
+                add_star = true;
+                state_name++;
+        }
+
         if (strcmp(state_name, param_name) == 0) {
-                return "$";
-        } else if (state_name[name_len] == '-' && /* check for '-' from "->" */
+                snprintf(buf, sizeof(buf), "%s$", add_star ? "*" : "");
+                return buf;
+        }
+
+        if (state_name[name_len] == '-' && /* check for '-' from "->" */
             strncmp(state_name, param_name, name_len) == 0) {
-                snprintf(buf, sizeof(buf), "$%s", state_name + name_len);
+                snprintf(buf, sizeof(buf), "%s$%s",
+                         add_star ? "*" : "", state_name + name_len);
                 return buf;
-        } else if (state_name[0] == '*' && strcmp(state_name + 1, param_name) == 0) {
-                return "*$";
         }
         return NULL;
 }
 
 const char *get_param_name_var_sym(const char *name, struct symbol *sym)