diff --git a/DESCRIPTION b/DESCRIPTION index d0612f20..ad7cd806 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: hesim Type: Package Title: Health Economic Simulation Modeling and Decision Analysis -Version: 0.5.6 +Version: 0.5.7 Authors@R: c( person("Devin", "Incerti", , "devin.incerti@gmail.com", role = c("aut", "cre")), person("Jeroen P.", "Jansen", role = "aut"), diff --git a/NEWS.md b/NEWS.md index b1e87d34..d569eea8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,8 @@ +## hesim 0.5.7 +Fix memory access issue identified in piecewise exponential distributions by +ensuring that the `time` and `rate` vectors are of the same length. Previously, +an off-by-one allocation could cause undefined behavior on some systems. + ## hesim 0.5.6 Ensure compatibility with `ggplot v4.0.0`. diff --git a/cran-comments.md b/cran-comments.md index c3e88417..6401ec47 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,9 +1,10 @@ ## Release summary -The purpose of this release is to fix errors caused by the latest release of -ggplot2. This is a resubmission that: +The purpose of this release is to fix memory access issues identified by +`clang-ASAN` and `gcc-ASAN` during the CRAN checks. -1. Updates a broken link for the data.table website. -2. Ensures all examples complete in under 10 seconds during CRAN checks. +The error was first reproduced on R-hub `clang-asan` and `gcc-asan`. After +the fix, it was then confirmed that `clang-asan` and `gcc-asan` did not +produce any errors. ## R CMD check results 0 errors | 0 warnings | 0 notes diff --git a/inst/include/hesim/statmods/statmods.h b/inst/include/hesim/statmods/statmods.h index c4014b51..e9bec80c 100644 --- a/inst/include/hesim/statmods/statmods.h +++ b/inst/include/hesim/statmods/statmods.h @@ -169,7 +169,7 @@ class surv : public statmod { } else if (dist_name == "pwexp"){ int n_times = params_surv.pwexp_aux_.time_.size(); - std::vector rate(n_times + 1, 0.0); + std::vector rate(n_times, 0.0); d = new stats::piecewise_exponential(rate, params_surv.pwexp_aux_.time_); } diff --git a/inst/include/hesim/stats/distributions.h b/inst/include/hesim/stats/distributions.h index f96e8eae..1a13cb24 100644 --- a/inst/include/hesim/stats/distributions.h +++ b/inst/include/hesim/stats/distributions.h @@ -310,6 +310,25 @@ class piecewise_exponential : public distribution { std::vector cumrate_; ///< cumulative rate parameter up to each time std::vector time_; ///& time, const std::vector& rate) { + if (time.size() != rate.size()) { + std::ostringstream oss_time, oss_rate; + for (auto x : time) oss_time << x << " "; + for (auto x : rate) oss_rate << x << " "; + Rcpp::stop("'time' and 'rate' must be the same length.\n" + + std::string("time: ") + oss_time.str() + "\n" + + std::string("rate: ") + oss_rate.str()); + } + } public: /** @@ -317,6 +336,8 @@ class piecewise_exponential : public distribution { * Instantiates an exponential distribution with a given rate parameter. */ piecewise_exponential(std::vector rate, std::vector time){ + check_same_length(time, rate); + rate_ = rate; time_ = time; cumrate_.resize(rate_.size()); diff --git a/tests/testthat/test-cpp-distributions.R b/tests/testthat/test-cpp-distributions.R index 4c9a5e89..f633908e 100644 --- a/tests/testthat/test-cpp-distributions.R +++ b/tests/testthat/test-cpp-distributions.R @@ -96,6 +96,13 @@ test_that("pwexp", { expect_true(all(r >= max(time) + 1)) }) +# An error is thrown if time and rate are not the same length +expect_error( + new(PwExp, rate = c(1, 2), time = c(0, 2, 4)), + "'time' and 'rate' must be the same length." +) + + # Weibull distribution (AFT) --------------------------------------------------- test_that("weibull", { Weibull <- module$weibull