diff --git a/Changes b/Changes index b377e110b..b0d64fbf5 100644 --- a/Changes +++ b/Changes @@ -68,6 +68,7 @@ Verilator 5.037 devel * Fix casting reals to large integrals (#6085). [Todd Strader] * Fix nested hier blocks workers error (#6087). [Bartłomiej Chmiel, Antmicro Ltd.] * Fix `--lib-create` with double-underscore (#6099). +* Fix decoding octal string escapes with 1-2 digits (#6108). Verilator 5.036 2025-04-27 diff --git a/src/V3String.cpp b/src/V3String.cpp index 7cd304692..ba0fcbfc7 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -160,16 +160,18 @@ string VString::unquoteSVString(const string& text, string& errOut) { if (std::isdigit(*cp)) { octal_val = octal_val * 8 + (*cp - '0'); if (++octal_digits == 3) { - octal_digits = 0; - quoted = false; newtext += octal_val; + octal_digits = 0; + octal_val = 0; + quoted = false; } } else { if (octal_digits) { // Spec allows 1-3 digits - octal_digits = 0; - quoted = false; newtext += octal_val; + octal_digits = 0; + octal_val = 0; + quoted = false; --cp; // Backup to reprocess terminating character as non-escaped continue; } @@ -200,6 +202,11 @@ string VString::unquoteSVString(const string& text, string& errOut) { } } } else if (*cp == '\\') { + if (octal_digits) { + newtext += octal_val; + octal_digits = 0; + octal_val = 0; + } quoted = true; octal_digits = 0; } else { diff --git a/test_regress/t/t_string_octal.py b/test_regress/t/t_string_octal.py new file mode 100755 index 000000000..f989a35fb --- /dev/null +++ b/test_regress/t/t_string_octal.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_string_octal.v b/test_regress/t/t_string_octal.v new file mode 100644 index 000000000..035c31a7b --- /dev/null +++ b/test_regress/t/t_string_octal.v @@ -0,0 +1,43 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checko(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); + +module t; + string s; + initial begin + s = $sformatf("\099 \119 \121"); // Q Q Q + // $display("%o %o %o %o %o", s[0], s[1], s[2], s[3], s[4]); + // Results vary by simulator. Some possibilities: + // 0 0 0 0 0 + // 40 71 71 40 11 + // 71 71 40 11 071 + + s = $sformatf("\088 \108 \110"); // H H H + // $display("%o %o %o %o %o", s[0], s[1], s[2], s[3], s[4]); + // Results vary by simulator. Some possibilities: + // 0 0 0 0 0 + // 40 70 70 40 10 + // 70 70 40 10 70 + + s = $sformatf("\102\3\12."); // B\023\312. + // $display("%o %o %o %o %o", s[0], s[1], s[2], s[3], s[4]); + `checko(s[0], 8'o102); + `checko(s[1], 8'o003); + `checko(s[2], 8'o012); + `checko(s[3], 8'o056); + + s = $sformatf("\102.\3.\12\103"); // B.\023.C + // $display("%o %o %o %o %o", s[0], s[1], s[2], s[3], s[4]); + `checko(s[0], 8'o102); + `checko(s[2], 8'o003); + `checko(s[4], 8'o012); + `checko(s[5], 8'o103); + $display("*-* All Finished *-*"); + $finish; + end +endmodule