Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

covr with option(covr.record_tests = TRUE) segfaults with large tests #503

Closed
dgkf opened this issue May 23, 2022 · 0 comments
Closed

covr with option(covr.record_tests = TRUE) segfaults with large tests #503

dgkf opened this issue May 23, 2022 · 0 comments

Comments

@dgkf
Copy link
Contributor

dgkf commented May 23, 2022

Posting this primarily for myself since it's an issue related to code I contributed (or rather with R itself) and plan to add some guardrails to prevent. It's extremely rare, but very opaque when it occurs.

Overview

When options(covr.record_tests = TRUE), the call stack of each unique test is recorded alongside the trace hits. These are written out with the .counters environments to .Rds files and read back in to aggregate coverage. However, R's .Rds deserializer can segfault when a call has an enormous number of arguments (documented in this comment in the R source referenced in my Rlang bug report).

Specific Example

This was encountered while running covr against the fs package with options(covr.record_tests = TRUE), which has one test that checks against super long file paths by calling the fs::path function with 100K arguments. R will segfault when trying to deserialize this call from .Rds when reading back in the .counters object.

Proposed Fix

This is an exceedingly rare circumstance, but one that produces rather indecipherable crash. To avoid this scenario, I propose truncating calls that exceed some conservative limit (say, 10K arguments, which is safely below the 25K minimum to produce the crash on my system).

A small pre-processing step would be needed before this line, for example:

max_call_len <- 1e4 + 1
call_lengths <- vapply(test, length, numeric(1L))
if (any(call_lengths > max_call_len)) {
  warning("A large call was captured as part of a test and will be truncated.")
}

test <- lapply(test, head, max_call_len)

Even if this behavior is resolved in a future version of R, it would be nice to conditionally make this truncation for older versions of R where this would still be problematic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant