Fix `--coverage-expr` null pointer dereference (#6181)

This commit is contained in:
Igor Zaworski 2025-07-16 18:07:34 +02:00 committed by GitHub
parent abd509ce53
commit 826e5b0826
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 191 additions and 5 deletions

View File

@ -39,17 +39,28 @@ class ExprCoverageEligibleVisitor final : public VNVisitor {
// STATE
bool m_eligible = true;
static bool elemDTypeEligible(const AstNodeDType* dtypep) {
dtypep = dtypep->skipRefp();
if (AstNodeDType* const dtp = dtypep->virtRefDTypep()) {
if (!elemDTypeEligible(dtp)) return false;
}
if (AstNodeDType* const dtp = dtypep->virtRefDType2p()) {
if (!elemDTypeEligible(dtp)) return false;
}
return !VN_IS(dtypep, ClassRefDType);
}
void visit(AstNodeVarRef* nodep) override {
AstNodeDType* dtypep = nodep->varp()->dtypep();
// Class objecs and references not supported for expression coverage
// Class objects and references not supported for expression coverage
// because the object may not persist until the point at which
// coverage data is gathered
// This could be resolved in the future by protecting against dereferrencing
// null pointers when cloning the expression for expression coverage
if (VN_CAST(dtypep, ClassRefDType)) {
m_eligible = false;
} else {
if (dtypep && elemDTypeEligible(dtypep)) {
iterateChildren(nodep);
} else {
m_eligible = false;
}
}
@ -858,7 +869,6 @@ class CoverageVisitor final : public VNVisitor {
!= strs[!term.m_objective].end())
impossible = true;
}
if (!redundant) expr.push_back(term);
}
if (!impossible) m_exprs.push_back(std::move(expr));

View File

@ -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(verilator_flags2=['--coverage-expr'])
test.execute()
test.passes()

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class Class1;
int value0 = 7;
endclass
module t;
initial begin
int i = 0;
Class1 q[15];
for (int j = 0; j < 15; j = j + 1) begin
Class1 x = new;
q[j] = x;
end
while (i < 15) begin
if ((q[i].value0 > 8) || (q[i].value0 < 5)) $stop;
i += 1;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -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(verilator_flags2=['--coverage-expr'])
test.execute()
test.passes()

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class Class1;
int value0 = 7;
endclass
module t;
initial begin
int i = 0;
Class1 q[int] = '{};
for (int j = 0; j < 15; j = j + 1) begin
Class1 x = new;
q[j] = x;
end
while (i < 15) begin
if ((q[i].value0 > 8) || (q[i].value0 < 5)) $stop;
i += 1;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -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(verilator_flags2=['--coverage-expr'])
test.execute()
test.passes()

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class Class1;
int value0 = 7;
endclass
module t;
initial begin
int i = 0;
Class1 q[] = new [15];
for (int j = 0; j < 15; j = j + 1) begin
Class1 x = new;
q[j] = x;
end
while (i < 15) begin
if ((q[i].value0 > 8) || (q[i].value0 < 5)) $stop;
i += 1;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -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(verilator_flags2=['--coverage-expr'])
test.execute()
test.passes()

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
class Class1;
int value0 = 7;
endclass
module t;
initial begin
int i = 0;
Class1 q[$];
repeat(15) begin
Class1 x = new;
q = { q, x };
end
while (i < q.size()) begin
if ((q[i].value0 > 8) || (q[i].value0 < 5)) $stop;
i += 1;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule