1
0
Fork
You've already forked unserializeData
0
Bits of R unserialize() (© R Core Team, GPL ≥ 2) rewritten in R to only allow non-executable data in.
  • R 97.4%
  • Makefile 2.6%
2026年07月10日 16:04:17 +03:00
inst/testdata Use 4 GiB of memory for large memory tests, not 16 2024年05月20日 10:12:07 +03:00
man Document and test info_rds return value 2024年05月11日 19:34:46 +03:00
R More informative failure for wrong magic number 2026年07月10日 16:04:17 +03:00
tests More informative failure for wrong magic number 2026年07月10日 16:04:17 +03:00
.gitignore README: install from Codeberg packages 2024年05月11日 21:03:29 +03:00
.Rbuildignore README: install from Codeberg packages 2024年05月11日 21:03:29 +03:00
DESCRIPTION Drop the Date field from DESCRIPTION 2024年11月20日 13:46:03 +03:00
Makefile README: install from Codeberg packages 2024年05月11日 21:03:29 +03:00
NAMESPACE Tweak the native-endianness guess, add test files 2024年05月11日 17:11:12 +03:00
README.md README: install from Codeberg packages 2024年05月11日 21:03:29 +03:00

unserializeData

What is this?

This is a pure-R implementation of a reader for a strict subset of R serialization format. Use its functions to load data-only *.rds or *.RData files:

saveRDS(volcano, path)
stopifnot(all.equal(volcano, read_data_rds(path)))
saveRDS(function() take_over_your_computer(), path)
read_data_rds(path)
# Error: Deliberately refusing to load data of type CLOSXP (code 3) that may be used as an attack payload.

Installation

install.packages(
	'unserializeData',
	repos = 'https://codeberg.org/api/packages/aitap/cran'
)

Poke me if you'd like to see it on CRAN. We're zero-dependency and should pass R CMD check --as-cran most of the time.

Why a strict subset?

R code trusts the internal state of the objects it works with. Any time an object contains something executable, an attacker can manipulate it to cause malicious actions when executed. This includes promises in environments, model formulas, ALTREP state, and who knows what else.

But if we only read simple vectors, matrices, arrays without ever letting ourselves compute on the language, the dangerous executable code has nowhere to come from, and the data should be safe to process.

Why write it in R?

R is a memory-safe language. A misjudged buffer size will result in an error, not damage the state of the program. Unbounded recursion will be caught by the runtime and safely stopped without spilling over the stack memory area.

What are the downsides?

Many kinds of objects (e.g. most model objects) are impossible to save in this format. It is only suitable for very simple objects.

This is completely secure, right?

Sorry, no.

R data streams are typically compressed. It is much harder but still not impossible to attack the decompressor.

Since we allow strings in, some code may call eval(parse(text=...)) on untrusted data (or glue::glue), at which point we are back to square one.

Some data (text or imagery) may present an attack on the operator instead of the R process.

Patches?

Welcome.