From 0ad589eaca003bba5fd7ec3dffc1f98dd35a2eeb Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 25 Oct 2011 15:57:05 -0700 Subject: [PATCH] V0.9: Improve the out of range check in tgt-vhdl/stmt.cc Promote the unsigned values to long to get a good comparison and on a machine where an unsigned is the same size as a long (32 bit) assert that the unsigned values are constrained to fit into a long. It's unlikely the values needed to create invalid results would ever happen, but this patch makes sure it doesn't go undetected. --- tgt-vhdl/stmt.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 7d217eb09..c03572ab0 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -1,7 +1,7 @@ /* * VHDL code generation for statements. * - * Copyright (C) 2008-2009 Nick Gasson (nick@nickg.me.uk) + * Copyright (C) 2008-2011 Nick Gasson (nick@nickg.me.uk) * * 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 @@ -1161,6 +1161,15 @@ static bool process_signal(vhdl_binop_expr *all, vhdl_var_ref *test, } unsigned ewid = ivl_expr_width(expr); + if (sizeof(unsigned) >= sizeof(long)) { + // Since we will be casting i (constrained by swid) to a long make sure + // it will fit into a long. This is actually off by one, but this is the + // best we can do since on 32 bit machines an unsigned and long are the + // same size. + assert(swid <= static_cast(numeric_limits::max())); + // We are also going to cast ewid to long so check it as well. + assert(ewid <= static_cast(numeric_limits::max())); + } for (unsigned i = 0; i < swid; i++) { // Generate a comparison for this bit position vhdl_binop_expr *cmp; @@ -1170,7 +1179,8 @@ static bool process_signal(vhdl_binop_expr *all, vhdl_var_ref *test, // Check if this is an out of bounds access. If this is a casez // then check against a constant 'x' for the out of bound bits // otherwise skip the check (casex). - if (i + sbase >= ewid || i + sbase < 0) { + if (static_cast(i) + sbase >= static_cast(ewid) || + static_cast(i) + sbase < 0) { if (is_casez) { // Get the current test bit. type = vhdl_type::nunsigned(width);