summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2020-01-22 16:05:13 -0800
committerJohn Levon <john.levon@joyent.com>2020-02-03 07:14:33 -0800
commit31ad075e90bf5afda8ab4b8cc4d3ca3e89946115 (patch)
treee90e74541c7d3050613b2a614c184c572582223e
parent2d85dedb8eaa3ba69c85560030efe4cbc815efb8 (diff)
downloadillumos-joyent-31ad075e90bf5afda8ab4b8cc4d3ca3e89946115.tar.gz
12257 resync smatch to 0.6.1-rc1-il-4
Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Robert Mustacchi <rm@fingolfin.org> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/tools/smatch/Makefile3
-rw-r--r--usr/src/tools/smatch/src/Makefile3
-rw-r--r--usr/src/tools/smatch/src/check_list.h1
-rw-r--r--usr/src/tools/smatch/src/check_locking.c9
-rw-r--r--usr/src/tools/smatch/src/lib.c29
-rw-r--r--usr/src/tools/smatch/src/lib.h15
-rw-r--r--usr/src/tools/smatch/src/machine.h2
-rw-r--r--usr/src/tools/smatch/src/pre-process.c8
-rw-r--r--usr/src/tools/smatch/src/smatch.h11
-rw-r--r--usr/src/tools/smatch/src/smatch_container_of.c59
-rw-r--r--usr/src/tools/smatch/src/smatch_db.c90
-rw-r--r--usr/src/tools/smatch/src/smatch_fresh_alloc.c195
-rw-r--r--usr/src/tools/smatch/src/smatch_math.c20
-rw-r--r--usr/src/tools/smatch/src/smatch_mtag.c16
-rw-r--r--usr/src/tools/smatch/src/smatch_slist.c8
-rw-r--r--usr/src/tools/smatch/src/smatch_type.c2
-rw-r--r--usr/src/tools/smatch/src/validation/sm_locking2.c9
-rw-r--r--usr/src/tools/smatch/src/validation/sm_locking3.c9
-rw-r--r--usr/src/tools/smatch/src/validation/sm_locking4.c7
-rw-r--r--usr/src/tools/smatch/src/validation/sm_locking6.c16
-rw-r--r--usr/src/tools/smatch/src/validation/sm_locking7.c12
21 files changed, 353 insertions, 171 deletions
diff --git a/usr/src/tools/smatch/Makefile b/usr/src/tools/smatch/Makefile
index c8f3c74f78..902c874624 100644
--- a/usr/src/tools/smatch/Makefile
+++ b/usr/src/tools/smatch/Makefile
@@ -20,7 +20,7 @@
#
PROG = smatch
-SPARSE_VERSION = 0.6.1-rc1-il-3
+SPARSE_VERSION = 0.6.1-rc1-il-4
include ../Makefile.tools
@@ -123,6 +123,7 @@ SMATCH_OBJS += smatch_expression_stacks.o
SMATCH_OBJS += smatch_extra.o
SMATCH_OBJS += smatch_files.o
SMATCH_OBJS += smatch_flow.o
+SMATCH_OBJS += smatch_fresh_alloc.o
SMATCH_OBJS += smatch_fn_arg_link.o
SMATCH_OBJS += smatch_function_hooks.o
SMATCH_OBJS += smatch_function_info.o
diff --git a/usr/src/tools/smatch/src/Makefile b/usr/src/tools/smatch/src/Makefile
index e9fb252972..bc8b3071a1 100644
--- a/usr/src/tools/smatch/src/Makefile
+++ b/usr/src/tools/smatch/src/Makefile
@@ -1,4 +1,4 @@
-VERSION=0.6.1-rc1-il-3
+VERSION=0.6.1-rc1-il-4
########################################################################
# The following variables can be overwritten from the command line
@@ -226,6 +226,7 @@ SMATCH_OBJS += smatch_extra.o
SMATCH_OBJS += smatch_files.o
SMATCH_OBJS += smatch_flow.o
SMATCH_OBJS += smatch_fn_arg_link.o
+SMATCH_OBJS += smatch_fresh_alloc.o
SMATCH_OBJS += smatch_function_hooks.o
SMATCH_OBJS += smatch_function_info.o
SMATCH_OBJS += smatch_function_ptrs.o
diff --git a/usr/src/tools/smatch/src/check_list.h b/usr/src/tools/smatch/src/check_list.h
index b687018e48..1841676ce3 100644
--- a/usr/src/tools/smatch/src/check_list.h
+++ b/usr/src/tools/smatch/src/check_list.h
@@ -72,6 +72,7 @@ CK(register_array_values)
CK(register_nul_terminator)
CK(register_nul_terminator_param_set)
CK(register_statement_count)
+CK(register_fresh_alloc)
CK(register_kernel_user_data)
CK(register_kernel_user_data2)
diff --git a/usr/src/tools/smatch/src/check_locking.c b/usr/src/tools/smatch/src/check_locking.c
index 285a52cedf..9af6b46c46 100644
--- a/usr/src/tools/smatch/src/check_locking.c
+++ b/usr/src/tools/smatch/src/check_locking.c
@@ -1021,10 +1021,13 @@ static void check_lock(char *name, struct symbol *sym)
if (parent_is_gone_var_sym(sm->name, sm->sym))
goto swap_stree;
- if (sm->state != &locked && sm->state != &unlocked)
+ if (sm->state != &locked &&
+ sm->state != &unlocked &&
+ sm->state != &restore)
goto swap_stree;
- if (sm->state == &unlocked && is_EINTR(estate_rl(return_sm->state)))
+ if ((sm->state == &unlocked || sm->state == &restore) &&
+ is_EINTR(estate_rl(return_sm->state)))
goto swap_stree;
bucket = success_fail_positive(estate_rl(return_sm->state));
@@ -1032,7 +1035,7 @@ static void check_lock(char *name, struct symbol *sym)
add_range(&locked_lines, line, line);
locked_buckets[bucket] = true;
}
- if (sm->state == &unlocked) {
+ if (sm->state == &unlocked || sm->state == &restore) {
add_range(&unlocked_lines, line, line);
unlocked_buckets[bucket] = true;
}
diff --git a/usr/src/tools/smatch/src/lib.c b/usr/src/tools/smatch/src/lib.c
index bc80001d55..50241937b5 100644
--- a/usr/src/tools/smatch/src/lib.c
+++ b/usr/src/tools/smatch/src/lib.c
@@ -318,13 +318,7 @@ int funsigned_char = UNSIGNED_CHAR;
int preprocess_only;
-static enum { STANDARD_C89,
- STANDARD_C94,
- STANDARD_C99,
- STANDARD_C11,
- STANDARD_GNU11,
- STANDARD_GNU89,
- STANDARD_GNU99, } standard = STANDARD_GNU89;
+enum standard standard = STANDARD_GNU89;
int arch_m64 = ARCH_M64_DEFAULT;
int arch_msize_long = 0;
@@ -1313,6 +1307,8 @@ static void predefined_macros(void)
if (optimize_size)
predefine("__OPTIMIZE_SIZE__", 0, "1");
+ predefine("__PRAGMA_REDEFINE_EXTNAME", 1, "1");
+
// Temporary hacks
predefine("__extension__", 0, NULL);
predefine("__pragma__", 0, NULL);
@@ -1326,7 +1322,6 @@ static void predefined_macros(void)
break;
case ARCH_LP64:
predefine("__LP64__", 1, "1");
- predefine("__LP64", 1, "1");
predefine("_LP64", 1, "1");
break;
case ARCH_LLP64:
@@ -1389,32 +1384,38 @@ static void predefined_macros(void)
case MACH_SPARC32:
predefine("__sparc__", 1, "1");
predefine("__sparc", 1, "1");
+ predefine_nostd("sparc");
break;
case MACH_X86_64:
if (arch_m64 != ARCH_LP32) {
predefine("__x86_64__", 1, "1");
predefine("__x86_64", 1, "1");
+ predefine("__amd64__", 1, "1");
+ predefine("__amd64", 1, "1");
break;
}
/* fall-through */
case MACH_I386:
predefine("__i386__", 1, "1");
predefine("__i386", 1, "1");
- predefine("i386", 1, "1");
+ predefine_nostd("i386");
break;
}
- predefine("__PRAGMA_REDEFINE_EXTNAME", 1, "1");
-
-#ifdef __sun
+#if defined(__unix__)
predefine("__unix__", 1, "1");
predefine("__unix", 1, "1");
- predefine("unix", 1, "1");
+ predefine_nostd("unix");
+#endif
+
+
+#if defined(__sun__) || defined(__sun)
predefine("__sun__", 1, "1");
predefine("__sun", 1, "1");
- predefine("sun", 1, "1");
+ predefine_nostd("sun");
predefine("__svr4__", 1, "1");
#endif
+
}
static void create_builtin_stream(void)
diff --git a/usr/src/tools/smatch/src/lib.h b/usr/src/tools/smatch/src/lib.h
index de8f1132fa..70b2ba3928 100644
--- a/usr/src/tools/smatch/src/lib.h
+++ b/usr/src/tools/smatch/src/lib.h
@@ -134,6 +134,7 @@ enum phase {
extern void add_pre_buffer(const char *fmt, ...) FORMAT_ATTR(1);
extern void predefine(const char *name, int weak, const char *fmt, ...) FORMAT_ATTR(3);
+extern void predefine_nostd(const char *name);
extern int preprocess_only;
@@ -206,6 +207,20 @@ extern int arch_msize_long;
extern int arch_big_endian;
extern int arch_mach;
+enum standard {
+ STANDARD_NONE,
+ STANDARD_GNU,
+ STANDARD_C89,
+ STANDARD_GNU89 = STANDARD_C89 | STANDARD_GNU,
+ STANDARD_C94,
+ STANDARD_GNU94 = STANDARD_C94 | STANDARD_GNU,
+ STANDARD_C99,
+ STANDARD_GNU99 = STANDARD_C99 | STANDARD_GNU,
+ STANDARD_C11,
+ STANDARD_GNU11 = STANDARD_C11 | STANDARD_GNU,
+};
+extern enum standard standard;
+
extern void dump_macro_definitions(void);
extern struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **files);
extern struct symbol_list *__sparse(char *filename);
diff --git a/usr/src/tools/smatch/src/machine.h b/usr/src/tools/smatch/src/machine.h
index b46383ac1d..af5c96f16f 100644
--- a/usr/src/tools/smatch/src/machine.h
+++ b/usr/src/tools/smatch/src/machine.h
@@ -62,7 +62,7 @@ enum machine {
#define MACH_NATIVE MACH_RISCV64
#elif defined(__riscv) && (__riscv_xlen == 32)
#define MACH_NATIVE MACH_RISCV32
-#elif defined(__sparc_v9__)
+#elif defined(__sparc_v9__) || defined(__sparcv9)
#define MACH_NATIVE MACH_SPARC64
#elif defined(__sparc__) || defined(__sparc)
#define MACH_NATIVE MACH_SPARC32
diff --git a/usr/src/tools/smatch/src/pre-process.c b/usr/src/tools/smatch/src/pre-process.c
index c35cbcfb3c..5a9313a358 100644
--- a/usr/src/tools/smatch/src/pre-process.c
+++ b/usr/src/tools/smatch/src/pre-process.c
@@ -1568,6 +1568,14 @@ void predefine(const char *name, int weak, const char *fmt, ...)
do_define(value->pos, NULL, ident, NULL, value, attr);
}
+///
+// like predefine() but only if one of the non-standard dialect is chosen
+void predefine_nostd(const char *name)
+{
+ if ((standard & STANDARD_GNU) || (standard == STANDARD_NONE))
+ predefine(name, 1, "1");
+}
+
static int do_handle_define(struct stream *stream, struct token **line, struct token *token, int attr)
{
struct token *arglist, *expansion;
diff --git a/usr/src/tools/smatch/src/smatch.h b/usr/src/tools/smatch/src/smatch.h
index 062dffc9d2..6e0698085e 100644
--- a/usr/src/tools/smatch/src/smatch.h
+++ b/usr/src/tools/smatch/src/smatch.h
@@ -104,6 +104,12 @@ struct constraint {
};
DECLARE_PTR_LIST(constraint_list, struct constraint);
+struct alloc_info {
+ const char *fn;
+ int size_param, nr;
+};
+extern struct alloc_info *alloc_funcs;
+
struct bit_info {
unsigned long long set;
unsigned long long possible;
@@ -398,6 +404,7 @@ int sym_name_is(const char *name, struct expression *expr);
int get_const_value(struct expression *expr, sval_t *sval);
int get_value(struct expression *expr, sval_t *val);
int get_implied_value(struct expression *expr, sval_t *val);
+int get_implied_value_fast(struct expression *expr, sval_t *sval);
int get_implied_min(struct expression *expr, sval_t *sval);
int get_implied_max(struct expression *expr, sval_t *val);
int get_hard_max(struct expression *expr, sval_t *sval);
@@ -839,6 +846,7 @@ enum info_type {
NOSPEC_WB = 1036,
STMT_CNT = 1037,
TERMINATED = 1038,
+ FRESH_ALLOC = 1044,
/* put random temporary stuff in the 7000-7999 range for testing */
USER_DATA = 8017,
@@ -1249,6 +1257,7 @@ int get_offset_from_container_of(struct expression *expr);
char *get_container_name(struct expression *container, struct expression *expr);
/* smatch_mtag.c */
+mtag_t str_to_mtag(const char *str);
int get_string_mtag(struct expression *expr, mtag_t *tag);
int get_toplevel_mtag(struct symbol *sym, mtag_t *tag);
int create_mtag_alias(mtag_t tag, struct expression *expr, mtag_t *new);
@@ -1278,6 +1287,8 @@ bool is_nul_terminated(struct expression *expr);
/* check_kernel.c */
bool is_ignored_kernel_data(const char *name);
+bool is_fresh_alloc_var_sym(const char *var, struct symbol *sym);
+bool is_fresh_alloc(struct expression *expr);
static inline bool type_is_ptr(struct symbol *type)
{
return type &&
diff --git a/usr/src/tools/smatch/src/smatch_container_of.c b/usr/src/tools/smatch/src/smatch_container_of.c
index bd9039cf75..65d4a8d8ac 100644
--- a/usr/src/tools/smatch/src/smatch_container_of.c
+++ b/usr/src/tools/smatch/src/smatch_container_of.c
@@ -215,17 +215,17 @@ static char *get_stored_container_name(struct expression *container,
return NULL;
}
-char *get_container_name(struct expression *container, struct expression *expr)
+static char *get_container_name_helper(struct expression *container, struct expression *expr)
{
struct symbol *container_sym, *sym;
- struct expression *tmp;
static char buf[64];
char *ret, *shared;
bool star;
- int cnt;
expr = strip_expr(expr);
container = strip_expr(container);
+ if (!expr || !container)
+ return NULL;
ret = get_stored_container_name(container, expr);
if (ret)
@@ -233,24 +233,10 @@ char *get_container_name(struct expression *container, struct expression *expr)
sym = expr_to_sym(expr);
container_sym = expr_to_sym(container);
- if (sym && sym == container_sym)
- goto found;
-
- cnt = 0;
- while ((tmp = get_assigned_expr(container))) {
- container = strip_expr(tmp);
- if (cnt++ > 3)
- break;
- }
-
- cnt = 0;
- while ((tmp = get_assigned_expr(expr))) {
- expr = strip_expr(tmp);
- if (cnt++ > 3)
- break;
- }
-
-found:
+ if (!sym || !container_sym)
+ return NULL;
+ if (sym != container_sym)
+ return NULL;
if (container->type == EXPR_DEREF)
star = true;
@@ -262,13 +248,6 @@ found:
if (expr->type == EXPR_PREOP && expr->op == '&')
expr = strip_expr(expr->unop);
- sym = expr_to_sym(expr);
- if (!sym)
- return NULL;
- container_sym = expr_to_sym(container);
- if (!container_sym || sym != container_sym)
- return NULL;
-
shared = get_shared_str(expr, container);
if (!shared)
return NULL;
@@ -280,6 +259,30 @@ found:
return buf;
}
+char *get_container_name(struct expression *container, struct expression *expr)
+{
+ char *ret;
+
+ ret = get_container_name_helper(container, expr);
+ if (ret)
+ return ret;
+
+ ret = get_container_name_helper(get_assigned_expr(container), expr);
+ if (ret)
+ return ret;
+
+ ret = get_container_name_helper(container, get_assigned_expr(expr));
+ if (ret)
+ return ret;
+
+ ret = get_container_name_helper(get_assigned_expr(container),
+ get_assigned_expr(expr));
+ if (ret)
+ return ret;
+
+ return NULL;
+}
+
static bool is_fn_ptr(struct expression *expr)
{
struct symbol *type;
diff --git a/usr/src/tools/smatch/src/smatch_db.c b/usr/src/tools/smatch/src/smatch_db.c
index e932d315ab..70be64093d 100644
--- a/usr/src/tools/smatch/src/smatch_db.c
+++ b/usr/src/tools/smatch/src/smatch_db.c
@@ -768,16 +768,6 @@ static void match_call_marker(struct expression *expr)
sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", type_to_str(type));
}
-static char *show_offset(int offset)
-{
- static char buf[64];
-
- buf[0] = '\0';
- if (offset != -1)
- snprintf(buf, sizeof(buf), "(-%d)", offset);
- return buf;
-}
-
int is_recursive_member(const char *name)
{
char buf[256];
@@ -860,7 +850,7 @@ free:
return ret;
}
-static void print_struct_members(struct expression *call, struct expression *expr, int param, int offset, struct stree *stree,
+static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree,
void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
{
struct sm_state *sm;
@@ -902,23 +892,23 @@ static void print_struct_members(struct expression *call, struct expression *exp
// FIXME: simplify?
if (!add_star && strcmp(name, sm_name) == 0) {
if (is_address)
- snprintf(printed_name, sizeof(printed_name), "*$%s", show_offset(offset));
+ snprintf(printed_name, sizeof(printed_name), "*$");
else /* these are already handled. fixme: handle them here */
continue;
} else if (add_star && strcmp(name, sm_name) == 0) {
- snprintf(printed_name, sizeof(printed_name), "%s*$%s",
- is_address ? "*" : "", show_offset(offset));
+ snprintf(printed_name, sizeof(printed_name), "%s*$",
+ is_address ? "*" : "");
} 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->%s", add_star ? "*" : "",
- show_offset(offset), sm_name + len + 1);
+ "%s$->%s", add_star ? "*" : "",
+ sm_name + len + 1);
else
snprintf(printed_name, sizeof(printed_name),
- "%s$%s%s", add_star ? "*" : "",
- show_offset(offset), sm_name + len);
+ "%s$%s", add_star ? "*" : "",
+ sm_name + len);
} else {
continue;
}
@@ -930,67 +920,6 @@ free:
free_string(name);
}
-static int param_used_callback(void *_container, int argc, char **argv, char **azColName)
-{
- char **container = _container;
- static char buf[256];
-
- snprintf(buf, sizeof(buf), "%s", argv[0]);
- *container = buf;
- return 0;
-}
-
-static void print_container_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree,
- void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
-{
- struct expression *tmp;
- char *container = NULL;
- int offset;
- int holder_offset;
- char *p;
-
- if (!call->fn || call->fn->type != EXPR_SYMBOL || !call->fn->symbol)
- return;
-
- /*
- * We can't use the in-mem DB because we have to parse the function
- * first, then we know if it takes a container, then we know to pass it
- * the container data.
- *
- */
- run_sql(&param_used_callback, &container,
- "select key from return_implies where %s and type = %d and key like '%%$(%%' and parameter = %d limit 1;",
- get_static_filter(call->fn->symbol), CONTAINER, param);
- if (!container)
- return;
-
- p = strchr(container, '-');
- if (!p)
- return;
- offset = atoi(p);
- p = strchr(p, ')');
- if (!p)
- return;
- p++;
-
- tmp = get_assigned_expr(expr);
- if (tmp)
- expr = tmp;
-
- if (expr->type != EXPR_PREOP || expr->op != '&')
- return;
- expr = strip_expr(expr->unop);
- holder_offset = get_member_offset_from_deref(expr);
- if (-holder_offset != offset)
- return;
-
- expr = strip_expr(expr->deref);
- if (expr->type == EXPR_PREOP && expr->op == '*')
- expr = strip_expr(expr->unop);
-
- print_struct_members(call, expr, param, holder_offset, stree, callback);
-}
-
static void match_call_info(struct expression *call)
{
struct member_info_callback *cb;
@@ -1007,8 +936,7 @@ static void match_call_info(struct expression *call)
stree = get_all_states_stree(cb->owner);
i = 0;
FOR_EACH_PTR(call->args, arg) {
- print_struct_members(call, arg, i, -1, stree, cb->callback);
- print_container_struct_members(call, arg, i, stree, cb->callback);
+ print_struct_members(call, arg, i, stree, cb->callback);
i++;
} END_FOR_EACH_PTR(arg);
free_stree(&stree);
diff --git a/usr/src/tools/smatch/src/smatch_fresh_alloc.c b/usr/src/tools/smatch/src/smatch_fresh_alloc.c
new file mode 100644
index 0000000000..d7104f6b53
--- /dev/null
+++ b/usr/src/tools/smatch/src/smatch_fresh_alloc.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2019 Oracle.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
+ */
+
+/*
+ * There are a bunch of allocation functions where we allocate some memory,
+ * set up some struct members and then return the allocated memory. One
+ * nice thing about this is that we just one pointer to the allocated memory
+ * so what we can do is we can generate a mtag alias for it in the caller.
+ */
+
+#include "smatch.h"
+#include "smatch_slist.h"
+
+static int my_id;
+
+STATE(fresh);
+
+struct alloc_info *alloc_funcs;
+
+struct alloc_info kernel_allocation_funcs[] = {
+ {"kmalloc", 0},
+ {"kmalloc_node", 0},
+ {"kzalloc", 0},
+ {"kzalloc_node", 0},
+ {"vmalloc", 0},
+ {"__vmalloc", 0},
+ {"kvmalloc", 0},
+ {"kcalloc", 0, 1},
+ {"kmalloc_array", 0, 1},
+ {"sock_kmalloc", 1},
+ {"kmemdup", 1},
+ {"kmemdup_user", 1},
+ {"dma_alloc_attrs", 1},
+ {"pci_alloc_consistent", 1},
+ {"pci_alloc_coherent", 1},
+ {"devm_kmalloc", 1},
+ {"devm_kzalloc", 1},
+ {"krealloc", 1},
+ {"__alloc_bootmem", 0},
+ {"alloc_bootmem", 0},
+ {"dma_alloc_contiguous", 1},
+ {"dma_alloc_coherent", 1},
+ {},
+};
+
+struct alloc_info general_allocation_funcs[] = {
+ {"malloc", 0},
+ {"calloc", 0, 1},
+ {"memdup", 1},
+ {"realloc", 1},
+ {},
+};
+
+static int fresh_callback(void *fresh, int argc, char **argv, char **azColName)
+{
+ *(int *)fresh = 1;
+ return 0;
+}
+
+static int fresh_from_db(struct expression *call)
+{
+ int fresh = 0;
+
+ /* for function pointers assume everything is used */
+ if (call->fn->type != EXPR_SYMBOL)
+ return 0;
+
+ run_sql(&fresh_callback, &fresh,
+ "select * from return_states where %s and type = %d and parameter = -1 and key = '$' limit 1;",
+ get_static_filter(call->fn->symbol), FRESH_ALLOC);
+ return fresh;
+}
+
+bool is_fresh_alloc_var_sym(const char *var, struct symbol *sym)
+{
+ return get_state(my_id, var, sym) == &fresh;
+}
+
+bool is_fresh_alloc(struct expression *expr)
+{
+ sval_t sval;
+ int i;
+
+ if (!expr)
+ return false;
+
+ if (get_implied_value_fast(expr, &sval) && sval.value == 0)
+ return false;
+
+ if (get_state_expr(my_id, expr) == &fresh)
+ return true;
+
+ if (expr->type != EXPR_CALL)
+ return false;
+ if (fresh_from_db(expr))
+ return true;
+ i = -1;
+ while (alloc_funcs[++i].fn) {
+ if (sym_name_is(kernel_allocation_funcs[i].fn, expr->fn))
+ return true;
+ }
+ return false;
+}
+
+static void record_alloc_func(int return_id, char *return_ranges, struct expression *expr)
+{
+ if (!is_fresh_alloc(expr))
+ return;
+ sql_insert_return_states(return_id, return_ranges, FRESH_ALLOC, -1, "$", "");
+}
+
+static void set_unfresh(struct expression *expr)
+{
+ struct sm_state *sm;
+
+ sm = get_sm_state_expr(my_id, expr);
+ if (!sm)
+ return;
+ if (!slist_has_state(sm->possible, &fresh))
+ return;
+ // TODO call unfresh hooks
+ set_state_expr(my_id, expr, &undefined);
+}
+
+static void match_assign(struct expression *expr)
+{
+ set_unfresh(expr->right);
+}
+
+static void match_call(struct expression *expr)
+{
+ struct expression *arg;
+
+ FOR_EACH_PTR(expr->args, arg) {
+ set_unfresh(arg);
+ } END_FOR_EACH_PTR(arg);
+}
+
+static void set_fresh(struct expression *expr)
+{
+ expr = strip_expr(expr);
+ if (expr->type != EXPR_SYMBOL)
+ return;
+ set_state_expr(my_id, expr, &fresh);
+}
+
+static void returns_fresh_alloc(struct expression *expr, int param, char *key, char *value)
+{
+ if (param != -1 || !key || strcmp(key, "$") != 0)
+ return;
+ if (expr->type != EXPR_ASSIGNMENT)
+ return;
+
+ set_fresh(expr->left);
+}
+
+static void match_alloc(const char *fn, struct expression *expr, void *_size_arg)
+{
+ set_fresh(expr->left);
+}
+
+void register_fresh_alloc(int id)
+{
+ int i;
+
+ my_id = id;
+
+ if (option_project == PROJ_KERNEL)
+ alloc_funcs = kernel_allocation_funcs;
+ else
+ alloc_funcs = general_allocation_funcs;
+
+ i = -1;
+ while (alloc_funcs[++i].fn)
+ add_function_assign_hook(alloc_funcs[i].fn, &match_alloc, 0);
+
+ add_split_return_callback(&record_alloc_func);
+ select_return_states_hook(FRESH_ALLOC, &returns_fresh_alloc);
+ add_hook(&match_assign, ASSIGNMENT_HOOK);
+ add_hook(&match_call, FUNCTION_CALL_HOOK);
+}
diff --git a/usr/src/tools/smatch/src/smatch_math.c b/usr/src/tools/smatch/src/smatch_math.c
index 68ca445619..e6e033172f 100644
--- a/usr/src/tools/smatch/src/smatch_math.c
+++ b/usr/src/tools/smatch/src/smatch_math.c
@@ -1606,6 +1606,26 @@ int get_implied_value(struct expression *expr, sval_t *sval)
return 1;
}
+int get_implied_value_fast(struct expression *expr, sval_t *sval)
+{
+ struct range_list *rl;
+ static int recurse;
+ int ret = 0;
+
+ if (recurse)
+ return 0;
+
+ recurse = 1;
+ set_fast_math_only();
+ if (get_rl_helper(expr, RL_IMPLIED, &rl) &&
+ rl_to_sval(rl, sval))
+ ret = 1;
+ clear_fast_math_only();
+ recurse = 0;
+
+ return ret;
+}
+
int get_implied_min(struct expression *expr, sval_t *sval)
{
struct range_list *rl;
diff --git a/usr/src/tools/smatch/src/smatch_mtag.c b/usr/src/tools/smatch/src/smatch_mtag.c
index 37d1f18579..607ede688b 100644
--- a/usr/src/tools/smatch/src/smatch_mtag.c
+++ b/usr/src/tools/smatch/src/smatch_mtag.c
@@ -50,7 +50,7 @@
static int my_id;
-static mtag_t str_to_tag(const char *str)
+mtag_t str_to_mtag(const char *str)
{
unsigned char c[MD5_DIGEST_LENGTH];
unsigned long long *tag = (unsigned long long *)&c;
@@ -132,7 +132,7 @@ struct smatch_state *swap_mtag_return(struct expression *expr, struct smatch_sta
snprintf(buf, sizeof(buf), "%s %s %s %s", get_filename(), get_function(),
left_name, right_name);
- tag = str_to_tag(buf);
+ tag = str_to_mtag(buf);
tag_sval.type = estate_type(state);
tag_sval.uvalue = tag;
@@ -156,8 +156,8 @@ int get_string_mtag(struct expression *expr, mtag_t *tag)
return 0;
/* I was worried about collisions so I added a xor */
- xor = str_to_tag("__smatch string");
- *tag = str_to_tag(expr->string->data);
+ xor = str_to_mtag("__smatch string");
+ *tag = str_to_mtag(expr->string->data);
*tag = *tag ^ xor;
return 1;
@@ -177,7 +177,7 @@ int get_toplevel_mtag(struct symbol *sym, mtag_t *tag)
snprintf(buf, sizeof(buf), "%s %s",
(sym->ctype.modifiers & MOD_STATIC) ? get_filename() : "extern",
sym->ident->name);
- *tag = str_to_tag(buf);
+ *tag = str_to_mtag(buf);
return 1;
}
@@ -196,7 +196,7 @@ bool get_symbol_mtag(struct symbol *sym, mtag_t *tag)
snprintf(buf, sizeof(buf), "%s %s %s",
get_filename(), get_function(), sym->ident->name);
- *tag = str_to_tag(buf);
+ *tag = str_to_mtag(buf);
return true;
}
@@ -258,7 +258,7 @@ struct range_list *swap_mtag_seed(struct expression *expr, struct range_list *rl
name = expr_to_str(expr);
snprintf(buf, sizeof(buf), "%s %s %s", get_filename(), get_function(), name);
free_string(name);
- tag = str_to_tag(buf);
+ tag = str_to_mtag(buf);
sval.value = tag;
return alloc_rl(sval, sval);
}
@@ -284,7 +284,7 @@ int create_mtag_alias(mtag_t tag, struct expression *expr, mtag_t *new)
snprintf(buf, sizeof(buf), "%lld %d %s", tag, lines_from_start, str);
free_string(str);
- *new = str_to_tag(buf);
+ *new = str_to_mtag(buf);
sql_insert_mtag_alias(tag, *new);
return 1;
diff --git a/usr/src/tools/smatch/src/smatch_slist.c b/usr/src/tools/smatch/src/smatch_slist.c
index 5c20dd739c..c95133f282 100644
--- a/usr/src/tools/smatch/src/smatch_slist.c
+++ b/usr/src/tools/smatch/src/smatch_slist.c
@@ -78,11 +78,13 @@ void __print_stree(struct stree *stree)
{
struct sm_state *sm;
- printf("dumping stree at %d [%ld states]\n", get_lineno(), stree_count(stree));
+ option_debug++;
+ sm_msg("dumping stree [%ld states]", stree_count(stree));
FOR_EACH_SM(stree, sm) {
- printf("%s\n", show_sm(sm));
+ sm_printf("%s\n", show_sm(sm));
} END_FOR_EACH_SM(sm);
- printf("---\n");
+ sm_printf("---\n");
+ option_debug--;
}
/* NULL states go at the end to simplify merge_slist */
diff --git a/usr/src/tools/smatch/src/smatch_type.c b/usr/src/tools/smatch/src/smatch_type.c
index 7e2e29ade5..be54ced235 100644
--- a/usr/src/tools/smatch/src/smatch_type.c
+++ b/usr/src/tools/smatch/src/smatch_type.c
@@ -789,7 +789,7 @@ static int type_str_helper(char *buf, int size, struct symbol *type)
int n;
if (!type)
- return snprintf(buf, size, "<unknown>");
+ return snprintf(buf, size, "<null type>");
if (type->type == SYM_BASETYPE) {
return snprintf(buf, size, "%s", base_type_str(type));
diff --git a/usr/src/tools/smatch/src/validation/sm_locking2.c b/usr/src/tools/smatch/src/validation/sm_locking2.c
index 37ce24869d..23294b07a1 100644
--- a/usr/src/tools/smatch/src/validation/sm_locking2.c
+++ b/usr/src/tools/smatch/src/validation/sm_locking2.c
@@ -30,10 +30,9 @@ int func (void)
* check-command: smatch --project=kernel sm_locking2.c
*
* check-output-start
-sm_locking2.c:21 func() error: double unlock 'spin_lock:mylock'
-sm_locking2.c:26 func() warn: inconsistent returns 'spin_lock:mylock3'.
- Locked on: line 26
- Unlocked on: line 14
- line 25
+sm_locking2.c:21 func() error: double unlocked 'mylock' (orig line 17)
+sm_locking2.c:26 func() warn: inconsistent returns 'mylock3'.
+ Locked on : 26
+ Unlocked on: 25
* check-output-end
*/
diff --git a/usr/src/tools/smatch/src/validation/sm_locking3.c b/usr/src/tools/smatch/src/validation/sm_locking3.c
index c63ec5cab2..d69f005214 100644
--- a/usr/src/tools/smatch/src/validation/sm_locking3.c
+++ b/usr/src/tools/smatch/src/validation/sm_locking3.c
@@ -24,10 +24,9 @@ int func (void)
* check-command: smatch --project=kernel sm_locking3.c
*
* check-output-start
-sm_locking3.c:18 func() error: double unlock 'spin_lock:mylock'
-sm_locking3.c:20 func() warn: inconsistent returns 'spin_lock:mylock'.
- Locked on: line 16
- Unlocked on: line 10
- line 20
+sm_locking3.c:18 func() error: double unlocked 'mylock' (orig line 15)
+sm_locking3.c:20 func() warn: inconsistent returns 'mylock'.
+ Locked on : 16
+ Unlocked on: 10,20
* check-output-end
*/
diff --git a/usr/src/tools/smatch/src/validation/sm_locking4.c b/usr/src/tools/smatch/src/validation/sm_locking4.c
index 301fac7086..6c44a269ad 100644
--- a/usr/src/tools/smatch/src/validation/sm_locking4.c
+++ b/usr/src/tools/smatch/src/validation/sm_locking4.c
@@ -28,9 +28,8 @@ void func (void)
* check-command: smatch --project=kernel sm_locking4.c
*
* check-output-start
-sm_locking4.c:23 func() warn: inconsistent returns 'spin_lock:mylock'.
- Locked on: line 22
- line 23
- Unlocked on: line 16
+sm_locking4.c:23 func() warn: inconsistent returns 'mylock'.
+ Locked on : 22-23
+ Unlocked on: 16
* check-output-end
*/
diff --git a/usr/src/tools/smatch/src/validation/sm_locking6.c b/usr/src/tools/smatch/src/validation/sm_locking6.c
index 9366c2c11f..b59fb1321a 100644
--- a/usr/src/tools/smatch/src/validation/sm_locking6.c
+++ b/usr/src/tools/smatch/src/validation/sm_locking6.c
@@ -31,15 +31,11 @@ void func (void)
* check-command: smatch -p=kernel sm_locking6.c
*
* check-output-start
-sm_locking6.c:27 func() warn: inconsistent returns 'irqsave:flags'.
- Locked on: line 26
- Unlocked on: line 21
- line 24
- line 27
-sm_locking6.c:27 func() warn: inconsistent returns 'spin_lock:lock'.
- Locked on: line 26
- Unlocked on: line 21
- line 24
- line 27
+sm_locking6.c:27 func() warn: inconsistent returns 'flags'.
+ Locked on : 26
+ Unlocked on: 21,24,27
+sm_locking6.c:27 func() warn: inconsistent returns 'lock'.
+ Locked on : 26
+ Unlocked on: 21,24,27
* check-output-end
*/
diff --git a/usr/src/tools/smatch/src/validation/sm_locking7.c b/usr/src/tools/smatch/src/validation/sm_locking7.c
index f2177ff3e0..ca96bb6867 100644
--- a/usr/src/tools/smatch/src/validation/sm_locking7.c
+++ b/usr/src/tools/smatch/src/validation/sm_locking7.c
@@ -27,11 +27,11 @@ void func(int *y)
* check-command: smatch -p=kernel -I.. sm_locking7.c
*
* check-output-start
-sm_locking7.c:22 func() warn: inconsistent returns 'irqsave:flags'.
- Locked on: line 21
- Unlocked on: line 22
-sm_locking7.c:22 func() warn: inconsistent returns 'spin_lock:&lock'.
- Locked on: line 21
- Unlocked on: line 22
+sm_locking7.c:22 func() warn: inconsistent returns 'flags'.
+ Locked on : 21
+ Unlocked on: 22
+sm_locking7.c:22 func() warn: inconsistent returns 'lock'.
+ Locked on : 21
+ Unlocked on: 22
* check-output-end
*/