--- /dev/null	Fri Dec 21 15:00:08 2018
+++ new/usr/src/tools/smatch/src/check_signed.c	Fri Dec 21 15:00:08 2018
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2009 Dan Carpenter.
+ *
+ * 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
+ */
+
+/*
+ * Check for things which are signed but probably should be unsigned.
+ *
+ * Hm...  It seems like at this point in the processing, sparse makes all
+ * bitfields unsigned.  Which is logical but not what GCC does.
+ *
+ */
+
+#include "smatch.h"
+#include "smatch_extra.h"
+
+static int my_id;
+
+#define VAR_ON_RIGHT 0
+#define VAR_ON_LEFT 1
+
+static void match_assign(struct expression *expr)
+{
+	struct symbol *sym;
+	sval_t sval;
+	sval_t max;
+	sval_t min;
+	char *left_name, *right_name;
+
+	if (__in_fake_assign)
+		return;
+	if (expr->op == SPECIAL_AND_ASSIGN || expr->op == SPECIAL_OR_ASSIGN)
+		return;
+
+	sym = get_type(expr->left);
+	if (!sym || sym->type != SYM_BASETYPE) {
+		//sm_msg("could not get type");
+		return;
+	}
+	if (type_bits(sym) < 0 || type_bits(sym) >= 32) /* max_val limits this */
+		return;
+	if (!get_implied_value(expr->right, &sval))
+		return;
+	max = sval_type_max(sym);
+	if (sym != &bool_ctype && sym != &uchar_ctype &&
+	    sval_cmp(max, sval) < 0 &&
+	    !(sval.value < 256 && max.value == 127)) {
+		left_name = expr_to_str(expr->left);
+		right_name = expr_to_str(expr->right);
+		sm_warning("'%s' %s can't fit into %s '%s'",
+		       right_name, sval_to_numstr(sval), sval_to_numstr(max), left_name);
+		free_string(left_name);
+	}
+	min = sval_type_min(sym);
+	if (sval_cmp_t(&llong_ctype, min, sval) > 0) {
+		if (min.value == 0 && sval.value == -1) /* assigning -1 to unsigned variables is idiomatic */
+			return;
+		if (expr->right->type == EXPR_PREOP && expr->right->op == '~')
+			return;
+		if (expr->op == SPECIAL_SUB_ASSIGN || expr->op == SPECIAL_ADD_ASSIGN)
+			return;
+		if (sval_positive_bits(sval) == 7)
+			return;
+		left_name = expr_to_str(expr->left);
+		if (min.value == 0) {
+			sm_warning("assigning %s to unsigned variable '%s'",
+			       sval_to_str(sval), left_name);
+		} else {
+			sm_warning("value %s can't fit into %s '%s'",
+			       sval_to_str(sval), sval_to_str(min), left_name);
+		}
+		free_string(left_name);
+	}
+}
+
+static int cap_gt_zero_and_lt(struct expression *expr)
+{
+
+	struct expression *var = expr->left;
+	struct expression *tmp;
+	char *name1 = NULL;
+	char *name2 = NULL;
+	sval_t known;
+	int ret = 0;
+	int i;
+
+	if (!get_value(expr->right, &known) || known.value != 0)
+		return 0;
+
+	i = 0;
+	FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
+		if (!i++)
+			continue;
+		if (tmp->op == SPECIAL_LOGICAL_AND) {
+			struct expression *right = strip_expr(tmp->right);
+
+			if (right->op != '<' &&
+			    right->op != SPECIAL_UNSIGNED_LT &&
+			    right->op != SPECIAL_LTE &&
+			    right->op != SPECIAL_UNSIGNED_LTE)
+				return 0;
+
+			name1 = expr_to_str(var);
+			if (!name1)
+				goto free;
+
+			name2 = expr_to_str(right->left);
+			if (!name2)
+				goto free;
+			if (!strcmp(name1, name2))
+				ret = 1;
+			goto free;
+
+		}
+		return 0;
+	} END_FOR_EACH_PTR_REVERSE(tmp);
+
+free:
+	free_string(name1);
+	free_string(name2);
+	return ret;
+}
+
+static int cap_lt_zero_or_gt(struct expression *expr)
+{
+
+	struct expression *var = expr->left;
+	struct expression *tmp;
+	char *name1 = NULL;
+	char *name2 = NULL;
+	sval_t known;
+	int ret = 0;
+	int i;
+
+	if (!get_value(expr->right, &known) || known.value != 0)
+		return 0;
+
+	i = 0;
+	FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
+		if (!i++)
+			continue;
+		if (tmp->op == SPECIAL_LOGICAL_OR) {
+			struct expression *right = strip_expr(tmp->right);
+
+			if (right->op != '>' &&
+			    right->op != SPECIAL_UNSIGNED_GT &&
+			    right->op != SPECIAL_GTE &&
+			    right->op != SPECIAL_UNSIGNED_GTE)
+				return 0;
+
+			name1 = expr_to_str(var);
+			if (!name1)
+				goto free;
+
+			name2 = expr_to_str(right->left);
+			if (!name2)
+				goto free;
+			if (!strcmp(name1, name2))
+				ret = 1;
+			goto free;
+
+		}
+		return 0;
+	} END_FOR_EACH_PTR_REVERSE(tmp);
+
+free:
+	free_string(name1);
+	free_string(name2);
+	return ret;
+}
+
+static int cap_both_sides(struct expression *expr)
+{
+	switch (expr->op) {
+	case '<':
+	case SPECIAL_UNSIGNED_LT:
+	case SPECIAL_LTE:
+	case SPECIAL_UNSIGNED_LTE:
+		return cap_lt_zero_or_gt(expr);
+	case '>':
+	case SPECIAL_UNSIGNED_GT:
+	case SPECIAL_GTE:
+	case SPECIAL_UNSIGNED_GTE:
+		return cap_gt_zero_and_lt(expr);
+	}
+	return 0;
+}
+
+static int compare_against_macro(struct expression *expr)
+{
+	sval_t known;
+
+	if (expr->op != SPECIAL_UNSIGNED_LT)
+		return 0;
+
+	if (!get_value(expr->right, &known) || known.value != 0)
+		return 0;
+	return !!get_macro_name(expr->right->pos);
+}
+
+static int print_unsigned_never_less_than_zero(struct expression *expr)
+{
+	sval_t known;
+	char *name;
+
+	if (expr->op != SPECIAL_UNSIGNED_LT)
+		return 0;
+
+	if (!get_value(expr->right, &known) || known.value != 0)
+		return 0;
+
+	name = expr_to_str(expr->left);
+	sm_warning("unsigned '%s' is never less than zero.", name);
+	free_string(name);
+	return 1;
+}
+
+static void match_condition(struct expression *expr)
+{
+	struct symbol *type;
+	sval_t known;
+	sval_t min, max;
+	struct range_list *rl_left_orig, *rl_right_orig;
+	struct range_list *rl_left, *rl_right;
+
+	if (expr->type != EXPR_COMPARE)
+		return;
+
+	type = get_type(expr);
+	if (!type)
+		return;
+
+	/* screw it.  I am writing this to mark yoda code as buggy.
+	 * Valid comparisons between an unsigned and zero are:
+	 * 1) inside a macro.
+	 * 2) foo < LOWER_BOUND where LOWER_BOUND is a macro.
+	 * 3) foo < 0 || foo > X in exactly this format.  No Yoda.
+	 * 4) foo >= 0 && foo < X
+	 */
+	if (get_macro_name(expr->pos))
+		return;
+	if (compare_against_macro(expr))
+		return;
+	if (cap_both_sides(expr))
+		return;
+
+	/* This is a special case for the common error */
+	if (print_unsigned_never_less_than_zero(expr))
+		return;
+
+	/* check that one and only one side is known */
+	if (get_value(expr->left, &known)) {
+		if (get_value(expr->right, &known))
+			return;
+		rl_left_orig = alloc_rl(known, known);
+		rl_left = cast_rl(type, rl_left_orig);
+
+		min = sval_type_min(get_type(expr->right));
+		max = sval_type_max(get_type(expr->right));
+		rl_right_orig = alloc_rl(min, max);
+		rl_right = cast_rl(type, rl_right_orig);
+	} else if (get_value(expr->right, &known)) {
+		rl_right_orig = alloc_rl(known, known);
+		rl_right = cast_rl(type, rl_right_orig);
+
+		min = sval_type_min(get_type(expr->left));
+		max = sval_type_max(get_type(expr->left));
+		rl_left_orig = alloc_rl(min, max);
+		rl_left = cast_rl(type, rl_left_orig);
+	} else {
+		return;
+	}
+
+	if (!possibly_true_rl(rl_left, expr->op, rl_right)) {
+		char *name = expr_to_str(expr);
+
+		sm_warning("impossible condition '(%s) => (%s %s %s)'", name,
+		       show_rl(rl_left), show_special(expr->op),
+		       show_rl(rl_right));
+		free_string(name);
+	}
+
+	if (!possibly_false_rl(rl_left, expr->op, rl_right)) {
+		char *name = expr_to_str(expr);
+
+		sm_warning("always true condition '(%s) => (%s %s %s)'", name,
+		       show_rl(rl_left_orig), show_special(expr->op),
+		       show_rl(rl_right_orig));
+		free_string(name);
+	}
+}
+
+void check_signed(int id)
+{
+	my_id = id;
+
+	add_hook(&match_assign, ASSIGNMENT_HOOK);
+	add_hook(&match_condition, CONDITION_HOOK);
+}
