2 * smatch/smatch_strlen.c
4 * Copyright (C) 2013 Oracle.
6 * Licensed under the Open Software License version 1.1
14 #include "smatch_slist.h"
15 #include "smatch_extra.h"
18 * The trick with the my_equiv_id is that if we have:
20 * We don't know at that point what the strlen() is but we know it's equivalent
21 * to "foo" so maybe we can find the value of "foo" later.
23 static int my_equiv_id
;
25 static void set_strlen_equiv_undefined(struct sm_state
*sm
, struct expression
*mod_expr
)
27 set_state(sm
->owner
, sm
->name
, sm
->sym
, &undefined
);
30 static void match_strlen(const char *fn
, struct expression
*expr
, void *unused
)
32 struct expression
*right
;
33 struct expression
*str
;
34 struct expression
*len_expr
;
36 struct smatch_state
*state
;
38 right
= strip_expr(expr
->right
);
39 str
= get_argument_from_call_expr(right
->args
, 0);
40 len_expr
= strip_expr(expr
->left
);
42 len_name
= expr_to_var(len_expr
);
46 state
= __alloc_smatch_state(0);
47 state
->name
= len_name
;
48 state
->data
= len_expr
;
50 set_state_expr(my_equiv_id
, str
, state
);
53 static int get_strlen_from_string(struct expression
*expr
, struct range_list
**rl
)
58 len
= expr
->string
->length
;
59 sval
= sval_type_val(&int_ctype
, len
- 1);
60 *rl
= alloc_rl(sval
, sval
);
64 int get_implied_strlen(struct expression
*expr
, struct range_list
**rl
)
66 struct smatch_state
*state
;
72 return get_strlen_from_string(expr
, rl
);
75 state
= get_state_expr(my_equiv_id
, expr
);
76 if (!state
|| !state
->data
)
78 if (!get_implied_rl((struct expression
*)state
->data
, rl
))
83 int get_size_from_strlen(struct expression
*expr
)
85 struct range_list
*rl
;
88 if (!get_implied_strlen(expr
, &rl
))
91 if (sval_is_negative(max
) || sval_is_max(max
))
94 return max
.value
+ 1; /* add one because strlen doesn't include the NULL */
97 void register_strlen(int id
)
100 add_function_assign_hook("strlen", &match_strlen
, NULL
);
101 add_modification_hook(my_equiv_id
, &set_strlen_equiv_undefined
);