Fix a use after free bug in the tests. The way the SystemTest fixture works is that it takes a "FooProblem" object as a type, which contains a ceres::Problem and a ceres::Solver::Options object. The Options object also contains a linear_solver_ordering which contains double* which refer to memory that is allocated when a problem object is created. So it is important that the lifetime of the ceres::Problem object and the ceres::Solver::Options object be tied together. But we were violating this by creating a FooProblem object on the stack, grabbing its Options struct and passing it to the SystemTest fixture, which would then create another instance of FooProblem, grab its Problem object and copy the modified options struct into it. In the case where a user provided ordering was being used, this ordering would now be referring to memory allocated by the first FooProblem object, which would cause Ceres's internal ApplyOrdering function to fail. The fix is ofcourse to Problem and Options object that are born together. Change-Id: I07c377a9d5fcabbb6c7ca8aa3460206ce045ffa9
diff --git a/internal/ceres/generate_bundle_adjustment_tests.py b/internal/ceres/generate_bundle_adjustment_tests.py index b36cf66..89cf8c7 100644 --- a/internal/ceres/generate_bundle_adjustment_tests.py +++ b/internal/ceres/generate_bundle_adjustment_tests.py
@@ -121,15 +121,17 @@ TEST_F(BundleAdjustmentTest, %(test_class_name)s) { // NOLINT - Solver::Options options = *BundleAdjustmentProblem().mutable_solver_options(); - options.num_threads = %(num_threads)s; - options.linear_solver_type = %(linear_solver)s; - options.sparse_linear_algebra_library_type = %(sparse_backend)s; - options.preconditioner_type = %(preconditioner)s; + BundleAdjustmentProblem bundle_adjustment_problem; + Solver::Options* options = bundle_adjustment_problem.mutable_solver_options(); + options->num_threads = %(num_threads)s; + options->linear_solver_type = %(linear_solver)s; + options->sparse_linear_algebra_library_type = %(sparse_backend)s; + options->preconditioner_type = %(preconditioner)s; if (%(ordering)s) { - options.linear_solver_ordering.reset(); + options->linear_solver_ordering.reset(); } - RunSolverForConfigAndExpectResidualsMatch(options); + Problem* problem = bundle_adjustment_problem.mutable_problem(); + RunSolverForConfigAndExpectResidualsMatch(*options, problem); } } // namespace internal