From edfd3d72064df6e9690dd8d44cbc148f13dfc1a6 Mon Sep 17 00:00:00 2001 From: Varun Koyyalagunta Date: Thu, 12 Oct 2023 17:08:58 -0500 Subject: [PATCH] Fix large constant buffer overflow (#4556) --- include/verilated_funcs.h | 56 ++++++++-------- test_regress/t/t_struct_param_overflow.pl | 21 ++++++ test_regress/t/t_struct_param_overflow.v | 81 +++++++++++++++++++++++ 3 files changed, 130 insertions(+), 28 deletions(-) create mode 100755 test_regress/t/t_struct_param_overflow.pl create mode 100644 test_regress/t/t_struct_param_overflow.v diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index 22285812e..4037b23c4 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -2111,60 +2111,60 @@ static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o, VL_C_END_(obits, 8); } // -static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase, +static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP o, EData d0) VL_MT_SAFE { - WDataOutP o = obase + VL_WORDS_I(lsb); - o[0] = d0; + WDataOutP ohi = o + VL_WORDS_I(lsb); + ohi[0] = d0; VL_C_END_(obits, VL_WORDS_I(lsb) + 1); } -static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase, +static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP o, EData d1, EData d0) VL_MT_SAFE { - WDataOutP o = obase + VL_WORDS_I(lsb); - o[0] = d0; o[1] = d1; + WDataOutP ohi = o + VL_WORDS_I(lsb); + ohi[0] = d0; ohi[1] = d1; VL_C_END_(obits, VL_WORDS_I(lsb) + 2); } -static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase, +static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP o, EData d2, EData d1, EData d0) VL_MT_SAFE { - WDataOutP o = obase + VL_WORDS_I(lsb); - o[0] = d0; o[1] = d1; o[2] = d2; + WDataOutP ohi = o + VL_WORDS_I(lsb); + ohi[0] = d0; ohi[1] = d1; ohi[2] = d2; VL_C_END_(obits, VL_WORDS_I(lsb) + 3); } -static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase, +static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP o, EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE { - WDataOutP o = obase + VL_WORDS_I(lsb); - o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3; + WDataOutP ohi = o + VL_WORDS_I(lsb); + ohi[0] = d0; ohi[1] = d1; ohi[2] = d2; ohi[3] = d3; VL_C_END_(obits, VL_WORDS_I(lsb) + 4); } -static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase, +static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP o, EData d4, EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE { - WDataOutP o = obase + VL_WORDS_I(lsb); - o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3; - o[4] = d4; + WDataOutP ohi = o + VL_WORDS_I(lsb); + ohi[0] = d0; ohi[1] = d1; ohi[2] = d2; ohi[3] = d3; + ohi[4] = d4; VL_C_END_(obits, VL_WORDS_I(lsb) + 5); } -static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase, +static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP o, EData d5, EData d4, EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE { - WDataOutP o = obase + VL_WORDS_I(lsb); - o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3; - o[4] = d4; o[5] = d5; + WDataOutP ohi = o + VL_WORDS_I(lsb); + ohi[0] = d0; ohi[1] = d1; ohi[2] = d2; ohi[3] = d3; + ohi[4] = d4; ohi[5] = d5; VL_C_END_(obits, VL_WORDS_I(lsb) + 6); } -static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase, +static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP o, EData d6, EData d5, EData d4, EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE { - WDataOutP o = obase + VL_WORDS_I(lsb); - o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3; - o[4] = d4; o[5] = d5; o[6] = d6; + WDataOutP ohi = o + VL_WORDS_I(lsb); + ohi[0] = d0; ohi[1] = d1; ohi[2] = d2; ohi[3] = d3; + ohi[4] = d4; ohi[5] = d5; ohi[6] = d6; VL_C_END_(obits, VL_WORDS_I(lsb) + 7); } -static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase, +static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP o, EData d7, EData d6, EData d5, EData d4, EData d3, EData d2, EData d1, EData d0) VL_MT_SAFE { - WDataOutP o = obase + VL_WORDS_I(lsb); - o[0] = d0; o[1] = d1; o[2] = d2; o[3] = d3; - o[4] = d4; o[5] = d5; o[6] = d6; o[7] = d7; + WDataOutP ohi = o + VL_WORDS_I(lsb); + ohi[0] = d0; ohi[1] = d1; ohi[2] = d2; ohi[3] = d3; + ohi[4] = d4; ohi[5] = d5; ohi[6] = d6; ohi[7] = d7; VL_C_END_(obits, VL_WORDS_I(lsb) + 8); } diff --git a/test_regress/t/t_struct_param_overflow.pl b/test_regress/t/t_struct_param_overflow.pl new file mode 100755 index 000000000..859050d63 --- /dev/null +++ b/test_regress/t/t_struct_param_overflow.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2023 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_struct_param_overflow.v b/test_regress/t/t_struct_param_overflow.v new file mode 100644 index 000000000..97f3220ec --- /dev/null +++ b/test_regress/t/t_struct_param_overflow.v @@ -0,0 +1,81 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2023 by Varun Koyyalagunta. +// SPDX-License-Identifier: CC0-1.0 + +package config_pkg; + + localparam int unsigned N = 10; + + typedef struct packed { + logic [N-1:0][31:0] lo; + logic [N-1:0][31:0] hi; + logic [100-1:0][31:0] x; + int unsigned n; + } config_struct; + + function automatic logic subcheck(logic[31:0] lo, logic[31:0] hi, logic[31:0] val); + return lo <= val && val < hi; + endfunction + + function automatic logic check(config_struct cfg, logic[31:0] val); + logic[N-1:0] good = '0; + logic[N-1:0] bad = '0; + for (int i = 0; i < cfg.n; i++) begin + good[i] = subcheck(cfg.lo[i], cfg.hi[i], val); + end + for (int i = cfg.n; i < N; i++) begin + bad[i] = !(cfg.lo[i] == '0 && cfg.hi[i] == '0); + end + return good != '0 && bad == '0; + endfunction + +endpackage : config_pkg + +module t(/*AUTOARG*/ + // Inputs + clk +); + + input clk; + import config_pkg::*; + + parameter config_struct MY_CONFIG = '{ + lo: {((N-3)*32)'('0), 32'h00, 32'h10, 32'h20}, + hi: {((N-3)*32)'('0), 32'h10, 32'h20, 32'h30}, + x : 3200'h0deadbeef, + n : 3 + }; + + struct_submodule #(.MY_CONFIG(MY_CONFIG)) a_submodule_I (.clk); +endmodule : t + +module struct_submodule + import config_pkg::*; + #( + parameter config_struct MY_CONFIG = '0 + ) ( + input clk + ); + + logic [31:0] val; + logic c; + int count = 0; + + assign val = 3; + assign c = check(MY_CONFIG, count); + + always @(posedge clk) begin + count <= count + 1; + if (c != '1) begin + $error("c not 1"); + $stop; + end + if (count >= 10) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule : struct_submodule