From b2395aa67eff859d8ae97ac63f8b161fca19aa4d Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 25 Oct 2011 15:56:30 -0700 Subject: [PATCH] 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 7581113df..4e2f6c1af 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -1,7 +1,7 @@ /* * VHDL code generation for statements. * - * Copyright (C) 2008-2010 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 @@ -1312,6 +1312,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; @@ -1321,7 +1330,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);