Skip to content

Security

Felix Gündling edited this page Oct 7, 2019 · 4 revisions

Cista can be used to read data from untrusted sources. Therefore, it needs to have rigid checks to ensure that reading data does not lead to overflows (at deserialization or use). To improve security, Fuzzing (here: LLVM's LibFuzzer) is used. Fuzzing is implemented for different data structures. A short test is run through the CI environment for every commit.

For deserialization, there are different possibilities:

  • No checks: If you are using cista::offset mode, a simple reinterpret_cast<T>(ptr) is sufficient.
  • Simple checks: cista::deserialize<T>(buf) does the job. It checks the memory hierarchy only. All serialized data is checked so that every pointer T* is either a nullptr or points to a valid position within the buffer with enough bytes for T. Scalar values are checked to fit into the buffer at their position, too. Cyclic data structures are not checked "deeply" - so there might be pointers that point to data in the buffer that contains invalid pointers.
  • Deep check: cista::deserialize<T, cista::mode::DEEP_CHECK>(buf) ensures (in addition to the simple checks) that there is no dangling pointer - even for cyclic data structures like graphs. This provides maximum security.

If you are loading trusted data and just want to make sure, that the files did not change through a memory corruption, use cista::deserialize<T, cista::mode::UNCHECKED | cista::mode::WITH_INTEGRITY> and optionally cista::mode::WITH_VERSION. This loads the data without bounds checking (can be omitted if it was serialized with Cista) but checks if the file contents did change using a checksum.

Note that modifying serialized data may corrupt it in unexpected ways. Therefore, it is not safe to access modified deserialized data coming from untrusted sources. However, deserializing and reading data from untrusted sources (without modifying the data) is safe.