From 9b55c1a191a982c451f6da3f0d9014747d5e325b Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Tue, 22 Aug 2023 09:08:52 -0400 Subject: [PATCH] [Thermo] Fix segfault in deprecated newPhase factory function The shared_ptr goes out of scope at the end of the function, deleting the held ThermoPhase right as it's returned. Erroneous behavior introduced in f3e840dcbe (#1448). --- src/thermo/ThermoFactory.cpp | 22 +++++++++++++++++++++- test/thermo/ThermoPhase_Test.cpp | 11 +++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/thermo/ThermoFactory.cpp b/src/thermo/ThermoFactory.cpp index d639fd41b4..3c28121f3d 100644 --- a/src/thermo/ThermoFactory.cpp +++ b/src/thermo/ThermoFactory.cpp @@ -202,7 +202,27 @@ ThermoPhase* newPhase(const string& infile, string id) warn_deprecated("newPhase", "To be removed after Cantera 3.0; superseded by\n" "newThermo(const string&, const string&)."); - return newThermo(infile, id).get(); + size_t dot = infile.find_last_of("."); + if (dot == npos) { + newThermoModel(infile); + } + string extension; + extension = toLowerCopy(infile.substr(dot+1)); + string id_ = id; + if (id == "-") { + id_ = ""; + } + if (extension == "cti" || extension == "xml") { + throw CanteraError("newPhase", + "The CTI and XML formats are no longer supported."); + } + + AnyMap root = AnyMap::fromYamlFile(infile); + AnyMap& phase = root["phases"].getMapWhere("name", id_); + string model = phase["thermo"].asString(); + unique_ptr t(ThermoFactory::factory()->create(model)); + setupPhase(*t, phase, root); + return t.release(); } void addDefaultElements(ThermoPhase& thermo, const vector& element_names) { diff --git a/test/thermo/ThermoPhase_Test.cpp b/test/thermo/ThermoPhase_Test.cpp index af857d0a2a..a8c3923d1a 100644 --- a/test/thermo/ThermoPhase_Test.cpp +++ b/test/thermo/ThermoPhase_Test.cpp @@ -117,6 +117,17 @@ TEST_F(TestThermoMethods, setConcentrations) EXPECT_NEAR(thermo->moleFraction(2), -1e-8 / ctot, 1e-16); } +TEST(ThermoConstructors, newPhase) +{ + suppress_deprecation_warnings(); + // Test deprecated newPhase(infile, phasename) factory function + unique_ptr gas(newPhase("h2o2.yaml", "")); + gas->setState_TPX(400, 2 * OneAtm, "H2:1.0, O2:1.0"); + EXPECT_NEAR(gas->moleFraction("H2"), 0.5, 1e-8); + EXPECT_NEAR(gas->pressure(), 2 * OneAtm, 1e-5); + make_deprecation_warnings_fatal(); +} + class EquilRatio_MixFrac_Test : public testing::Test { public: