• Stars
    star
    144
  • Rank 254,171 (Top 6 %)
  • Language
    Rust
  • License
    MIT License
  • Created over 3 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Slitter is a C- and Rust-callable slab allocator implemented primarily in Rust, with some C for performance or to avoid unstable Rust features.

Slitter is a less footgunny slab allocator

Build Status

Slitter is a classically structured thread-caching slab allocator that's meant to help write reliable long-running programs.

Given this goal, Slitter does not prioritise speed. The primary goal is instead to help applications handle inevitable memory management errors--be it with built-in statistics, with runtime detection, or by controlling their blast radius--while keeping the allocator's performance competitive with the state of the art. The other important goal is to let applications customise how Slitter requests memory from the operating system.

See doc/fast_path.md for details on allocation performance. For the rest of the allocator at a high level, refer to doc/design.md. Due to the type-stability guarantee, external fragmentation is essentially out of scope, and the slab/bump pointer allocation scheme keeps internal fragmentation to a very low level (only for metadata and guard pages, on the order of 2-3%, more once we add internal guard pages).

Current guarantees:

  1. Slitter will detect mismatching classes when recycling allocations, and will often also crash when it receives an address that it does not manage. Without this guarantee, it's too easy for heap usage statistics to become useless, and for incorrectly paired release calls to turn into memory corruption, far from the erroneous call.

  2. Slitter does not have any in-band metadata. This means no metadata next to the application's allocations, ripe for buffer overflows (we maintain guard pages between data and metadata), and also no intrusive linked list that would be vulnerable to use-after-free.

  3. Slitter-allocated data has a stable type: once an address has been returned to the mutator for a given allocation class, that address will always be valid, and will always be used for data of that class. Per #2, Slitter does not use intrusive linked lists, so the data reflects what the application stored there, even once it has been recycled. This lets application code rely on benign use-after-free in non-blocking algorithms instead of, e.g., SMR. The guarantee also means that any double-free or malign use-after-free will only affect the faulty allocation class.

Future guarantees:

  1. Slitter will detect when an interior pointer is freed.

  2. Slitter will detect most buffer overflows that cross allocation classes, with guard pages.

  3. Slitter will always detect frees of addresses it does not manage.

  4. Slitter will detect most back-to-back double-frees.

Future features:

a. Slitter will let each allocation class determine how its backing memory should be allocated (e.g., cold data could live in a file-backed mapping for opt-in swapping).

b. Slitter will track the number of objects allocated and recycled in each allocation class.

c. Slitter will sample a small fraction of allocations for heap profiling.

How to use Slitter as a C library

In order to use Slitter as a C library, we must first build a static library with Cargo. Slitter can only be called from C via static linkage because Cargo will otherwise hide our C functions. However, this also exposes internal Rust symbols, so there can only be one statically linked Rust library in any executable.

See examples/demo.c for a sample integration, which also demonstrates some of the additional checks unlocked by explicit allocation class tags. Execute that file in sh (i.e., sh examples/demo.c) to build Slitter, build demo.c and link it against Slitter, and run the resulting demo executable.

The #ifdef MISMATCH section allocates an object of a derived struct type, and releases it as the base type. The base field is the first member of the derived struct, so a plain malloc/free interface is unable to tell the difference. However, since the caller must tell slitter_release what allocation class it expects the freed pointer to be in, Slitter can detect the mismatch.

How to use Slitter within a Rust uber-crate

When linking multiple Rust libraries with other languages like C or C++, one must build a single statically linked (crate-type = ["staticlib"]) Rust crate that depends on all the Rust libraries we want to expose, and make sure to re-export the public extern "C" definitions from each of the dependencies.

How to use Slitter from Rust

We haven't explored that use case, except for tests. You can look at the unit tests at the bottom on src/class.rs. TL;DR: create new Class objects (they're copiable wrappers around NonZeroU32), and call Class::allocate and Class::release.

More Repositories

1

verneuil

Verneuil is a VFS extension for SQLite that asynchronously replicates databases to S3-compatible blob stores.
C
418
star
2

umash

UMASH: a fast enough hash and fingerprint with collision bounds
Python
152
star
3

backtrace-unity

First-class error reporting for the Unity game engine.
C#
127
star
4

crashpad

A fork of Crashpad with file attachment support and other improvements.
C++
93
star
5

poireau

Poireau: a sampling allocation debugger
Python
86
star
6

dynamic_flag

A C library for runtime-flippable feature flags on Linux/x86-64, with negligible overhead in the common case
C
69
star
7

stuffed-record-stream

Backtrace.io's resilient log record framing format
C
35
star
8

backtrace-android

Error reporting for Android-based devices
Java
32
star
9

sqlite_protobuf

An updated fork of sqlite_protobuf (https://github.com/rgov/sqlite_protobuf), a SQLite extension for extracting values from serialized Protobuf messages.
C
27
star
10

go-bcd

Backtrace Crash Delivery for Go
Go
24
star
11

backtrace-cocoa

Backtrace for Apple devices
Swift
23
star
12

backtrace-csharp

C# Support for Backtrace
C#
19
star
13

bcd

Simple out-of-process invoker
C
16
star
14

backtrace-node

Backtrace object store integration for NodeJS.
TypeScript
10
star
15

backtrace-morgue

Object store client.
JavaScript
9
star
16

libunwindstack-ndk

C++
7
star
17

backtrace-go

Go integration with Backtrace object store.
Go
7
star
18

backtrace-js

Client-side Javascript integration into the Backtrace object store.
TypeScript
6
star
19

backtrace-javascript

TypeScript
6
star
20

backtrace-java

Java support for Backtrace
Java
5
star
21

backtrace-log4j

Java
3
star
22

breakpad

C++
3
star
23

umash-rs

An idiomatic Rust API for umash
Rust
3
star
24

backtrace-python

Python integration into the Backtrace object store.
Python
3
star
25

cdqs

Compiler debug quality suite
C
3
star
26

libbun

Unwinding API with support for multiple backends
C
3
star
27

ptrace-module-example

C
1
star
28

invoker

ATS crash-logger replacement
C
1
star
29

unity-asterax

Demo of a Unity integration.
C#
1
star
30

backtrace-log4j2

Java
1
star
31

backtrace-crashpad-cocoapod

A Cocoapods integration of Crashpad.
C++
1
star