From 567df9c29aae857326204fff99173ef00fe879ef Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 19 Sep 2022 13:25:28 +0200 Subject: [PATCH 1/2] vvp: Handle copying of empty dynamic array and queue An empty dynamic array or queue is represented by a null object in vvp. Currently when trying to copy such an object results in undefined behavior in various places. Either hitting an assert or causing a nullptr dereference. Make sure that the empty object is handled correctly by treating it as a special case. Signed-off-by: Lars-Peter Clausen --- vvp/vthread.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 41950c58e..93e368619 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -3000,7 +3000,14 @@ bool of_DIV_WR(vthread_t thr, vvp_code_t) */ bool of_DUP_OBJ(vthread_t thr, vvp_code_t) { - thr->push_object(thr->peek_object().duplicate()); + vvp_object_t src = thr->peek_object(); + + // If it is null push a new null object + if (src.test_nil()) + thr->push_object(vvp_object_t()); + else + thr->push_object(src.duplicate()); + return true; } @@ -5542,7 +5549,9 @@ bool of_SCOPY(vthread_t thr, vvp_code_t) thr->pop_object(tmp); vvp_object_t&dest = thr->peek_object(); - dest.shallow_copy(tmp); + // If it is null there is nothing to copy + if (!tmp.test_nil()) + dest.shallow_copy(tmp); return true; } @@ -6099,7 +6108,12 @@ static bool store_qobj(vthread_t thr, vvp_code_t cp, unsigned wid=0) vvp_object_t src; thr->pop_object(src); - queue->copy_elems(src, max_size); + // If it is null just clear the queue + if (src.test_nil()) + queue->erase_tail(0); + else + queue->copy_elems(src, max_size); + return true; } From 72e59fc626dfe32513873683a6bfb20cc366e0b5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 19 Sep 2022 18:26:32 +0200 Subject: [PATCH 2/2] Add regression tests for copying empty dynamic array and queue Check that it is possible to copy empty dynamic arrays and queues. If the target is a dynamic arrays there are two ways of copying. Through direct assignment as well as the array new operator. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_darray_copy_empty1.v | 17 +++++++++++++++++ ivtest/ivltests/sv_darray_copy_empty2.v | 17 +++++++++++++++++ ivtest/ivltests/sv_darray_copy_empty3.v | 18 ++++++++++++++++++ ivtest/ivltests/sv_darray_copy_empty4.v | 18 ++++++++++++++++++ ivtest/ivltests/sv_queue_copy_empty1.v | 19 +++++++++++++++++++ ivtest/ivltests/sv_queue_copy_empty2.v | 17 +++++++++++++++++ ivtest/regress-sv.list | 6 ++++++ ivtest/regress-vlog95.list | 6 ++++++ 8 files changed, 118 insertions(+) create mode 100644 ivtest/ivltests/sv_darray_copy_empty1.v create mode 100644 ivtest/ivltests/sv_darray_copy_empty2.v create mode 100644 ivtest/ivltests/sv_darray_copy_empty3.v create mode 100644 ivtest/ivltests/sv_darray_copy_empty4.v create mode 100644 ivtest/ivltests/sv_queue_copy_empty1.v create mode 100644 ivtest/ivltests/sv_queue_copy_empty2.v diff --git a/ivtest/ivltests/sv_darray_copy_empty1.v b/ivtest/ivltests/sv_darray_copy_empty1.v new file mode 100644 index 000000000..c237b8634 --- /dev/null +++ b/ivtest/ivltests/sv_darray_copy_empty1.v @@ -0,0 +1,17 @@ +// Check that it is possible to copy an empty dynamic array. + +module test; + + initial begin + int d1[]; + int d2[]; + d1 = '{1, 2, 3}; + d1 = d2; + if (d1.size() == 0 && d2.size() == 0) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_copy_empty2.v b/ivtest/ivltests/sv_darray_copy_empty2.v new file mode 100644 index 000000000..842810efd --- /dev/null +++ b/ivtest/ivltests/sv_darray_copy_empty2.v @@ -0,0 +1,17 @@ +// Check that it is possible to copy an empty queue to an dynamic array. + +module test; + + initial begin + int d[]; + int q[$]; + d = '{1, 2, 3}; + d = q; + if (d.size() == 0 && q.size() == 0) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_copy_empty3.v b/ivtest/ivltests/sv_darray_copy_empty3.v new file mode 100644 index 000000000..5464ce89e --- /dev/null +++ b/ivtest/ivltests/sv_darray_copy_empty3.v @@ -0,0 +1,18 @@ +// Check that it is possible to copy an empty dynamic array using a dynamic +// array new operation. + +module test; + + initial begin + int d1[]; + int d2[]; + d1 = '{1, 2, 3}; + d1 = new [2](d2); + if (d1.size() == 2 && d2.size() == 0) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_copy_empty4.v b/ivtest/ivltests/sv_darray_copy_empty4.v new file mode 100644 index 000000000..985222190 --- /dev/null +++ b/ivtest/ivltests/sv_darray_copy_empty4.v @@ -0,0 +1,18 @@ +// Check that it is possible to copy an empty queue to a dynamic array using a +// dynamic array new operation. + +module test; + + initial begin + int d[]; + int q[$]; + d = '{1, 2, 3}; + d = new [2](q); + if (d.size() == 2 && q.size() == 0) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_copy_empty1.v b/ivtest/ivltests/sv_queue_copy_empty1.v new file mode 100644 index 000000000..df028e635 --- /dev/null +++ b/ivtest/ivltests/sv_queue_copy_empty1.v @@ -0,0 +1,19 @@ +// Check that it is possible to copy an empty queue. + +module test; + + typedef int T[$]; + + initial begin + T q1; + T q2; + q1 = '{1, 2, 3}; + q1 = q2; + if (q1.size() == 0 && q2.size() == 0) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_copy_empty2.v b/ivtest/ivltests/sv_queue_copy_empty2.v new file mode 100644 index 000000000..3c6fcae95 --- /dev/null +++ b/ivtest/ivltests/sv_queue_copy_empty2.v @@ -0,0 +1,17 @@ +// Check that it is possible to copy an empty dynamic array to a queue. + +module test; + + initial begin + int q[$]; + int d[]; + q = '{1, 2, 3}; + q = d; + if (q.size() == 0 && d.size() == 0) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index acc997669..0ad90d0c3 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -551,6 +551,10 @@ sv_darray_args2 normal,-g2009 ivltests sv_darray_args2b normal,-g2009 ivltests sv_darray_args3 normal,-g2009 ivltests sv_darray_args4 normal,-g2009 ivltests +sv_darray_copy_empty1 normal,-g2009 ivltests +sv_darray_copy_empty2 normal,-g2009 ivltests +sv_darray_copy_empty3 normal,-g2009 ivltests +sv_darray_copy_empty4 normal,-g2009 ivltests sv_darray_decl_assign normal,-g2009 ivltests sv_darray_function normal,-g2009 ivltests sv_darray_oob_real normal,-g2009 ivltests @@ -612,6 +616,8 @@ sv_port_default14 CE,-g2009 ivltests sv_queue1 normal,-g2009 ivltests sv_queue2 normal,-g2009 ivltests sv_queue3 normal,-g2009 ivltests +sv_queue_copy_empty1 normal,-g2009 ivltests +sv_queue_copy_empty2 normal,-g2009 ivltests sv_queue_function1 normal,-g2009 ivltests sv_queue_function2 normal,-g2009 ivltests sv_queue_oob_real normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index 0aeb61f90..50bc4b235 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -344,6 +344,10 @@ sv_darray_args2 CE,-g2009,-pallowsigned=1 ivltests sv_darray_args2b CE,-g2009,-pallowsigned=1 ivltests sv_darray_args3 CE,-g2009,-pallowsigned=1 ivltests sv_darray_args4 CE,-g2009,-pallowsigned=1 ivltests # Also string +sv_darray_copy_empty1 CE,-g2009 ivltests +sv_darray_copy_empty2 CE,-g2009 ivltests +sv_darray_copy_empty3 CE,-g2009 ivltests +sv_darray_copy_empty4 CE,-g2009 ivltests sv_darray_decl_assign CE,-g2009,-pallowsigned=1 ivltests sv_darray_function CE,-g2009,-pallowsigned=1 ivltests sv_darray_oob_real CE,-g2009 ivltests @@ -481,6 +485,8 @@ pr3390385b CE,-g2009 ivltests # ++ pr3390385c CE,-g2009 ivltests # ++ pr3390385d CE,-g2009 ivltests # ++ pr3462145 CE,-g2009 ivltests # ++ +sv_queue_copy_empty1 CE,-g2009 ivltests # queue +sv_queue_copy_empty2 CE,-g2009 ivltests # queue sv_queue_function1 CE,-g2009,-pallowsigned=1 ivltests # queue sv_queue_function2 CE,-g2009,-pallowsigned=1 ivltests # queue sv_queue_oob_real CE,-g2009 ivltests # queue