2 * Copyright (C) 2015 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 #include "smatch_slist.h"
20 #include "smatch_extra.h"
24 static int get_str(void *_ret
, int argc
, char **argv
, char **azColName
)
31 *ret
= alloc_sname(argv
[0]);
36 static char *get_string_from_mtag(mtag_t tag
)
40 run_sql(get_str
, &str
,
41 "select value from mtag_data where tag = %lld and offset = 0 and type = %d;",
44 if ((unsigned long)str
== -1UL)
49 struct expression
*fake_string_from_mtag(mtag_t tag
)
55 str
= get_string_from_mtag(tag
);
58 return gen_string_expression(str
);
61 static void match_strcpy(const char *fn
, struct expression
*expr
, void *unused
)
63 struct expression
*dest
, *src
;
65 dest
= get_argument_from_call_expr(expr
->args
, 0);
66 src
= get_argument_from_call_expr(expr
->args
, 1);
67 src
= strip_expr(src
);
68 if (src
->type
== EXPR_STRING
)
69 set_state_expr(my_id
, dest
, alloc_state_str(src
->string
->data
));
72 struct state_list
*get_strings(struct expression
*expr
)
74 struct state_list
*ret
= NULL
;
75 struct smatch_state
*state
;
78 expr
= strip_expr(expr
);
79 if (expr
->type
== EXPR_STRING
) {
80 state
= alloc_state_str(expr
->string
->data
);
81 sm
= alloc_sm_state(my_id
, expr
->string
->data
, NULL
, state
);
82 add_ptr_list(&ret
, sm
);
86 if (expr
->type
== EXPR_CONDITIONAL
||
87 expr
->type
== EXPR_SELECT
) {
88 struct state_list
*true_strings
= NULL
;
89 struct state_list
*false_strings
= NULL
;
91 if (known_condition_true(expr
->conditional
))
92 return get_strings(expr
->cond_true
);
93 if (known_condition_false(expr
->conditional
))
94 return get_strings(expr
->cond_false
);
96 true_strings
= get_strings(expr
->cond_true
);
97 false_strings
= get_strings(expr
->cond_false
);
98 concat_ptr_list((struct ptr_list
*)true_strings
, (struct ptr_list
**)&false_strings
);
99 free_slist(&true_strings
);
100 return false_strings
;
103 sm
= get_sm_state_expr(my_id
, expr
);
107 return clone_slist(sm
->possible
);
110 static void match_assignment(struct expression
*expr
)
112 struct state_list
*slist
;
118 slist
= get_strings(strip_expr(expr
->right
));
122 if (ptr_list_size((struct ptr_list
*)slist
) == 1) {
123 sm
= first_ptr_list((struct ptr_list
*)slist
);
124 set_state_expr(my_id
, expr
->left
, sm
->state
);
129 static void match_string(struct expression
*expr
)
133 if (expr
->type
!= EXPR_STRING
)
135 if (expr
->string
->length
> 255)
138 if (!get_string_mtag(expr
, &tag
))
141 cache_sql(NULL
, NULL
, "insert or ignore into mtag_data values (%lld, %d, %d, '%q');",
142 tag
, 0, STRING_VALUE
, escape_newlines(expr
->string
->data
));
145 void register_strings(int id
)
149 add_function_hook("strcpy", &match_strcpy
, NULL
);
150 add_function_hook("strlcpy", &match_strcpy
, NULL
);
151 add_function_hook("strncpy", &match_strcpy
, NULL
);
153 add_hook(&match_assignment
, ASSIGNMENT_HOOK
);
154 add_hook(&match_string
, STRING_HOOK
);