A crate to help you copy things into raw buffers without invoking spooky action at a distance (undefined behavior).

Related tags

Command-line presser
Overview

πŸ—œ presser

Utilities to help make copying data around into raw, possibly-uninitialized buffers easier and safer.

Embark Embark Crates.io Published Docs Git Docs dependency status

presser can help you when copying data into raw buffers. One primary use-case is copying data into graphics-api-allocated buffers which will then be accessed by the GPU. Common methods for doing this right now in Rust can often invoke UB in subtle and hard-to-see ways. For example, viewing an allocated but uninitialized buffer as an &mut [u8] is instantly undefined behavior*, and transmuteing even a T: Copy type which has any padding bytes in its layout as a &[u8] to be the source of a copy is also instantly undefined behavior, in both cases because it is invalid to create a reference to an invalid value (and uninitialized memory is an invalid u8), even if your code never actually accesses that memory. This immediately makes what seems like the most straightforward way to copy data into buffers unsound 😬

* If you're currently thinking to yourself "bah! what's the issue? surely an uninit u8 is just any random bit pattern and that's fine we don't care," check out this blog post by @RalfJung, one of the people leading the effort to better define Rust's memory and execution model. As is explored in that blog post, an uninit piece of memory is not simply an arbitrary bit pattern, it is a wholly separate state about a piece of memory, outside of its value, which lets the compiler perform optimizations that reorder, delete, and otherwise change the actual execution flow of your program in ways that cannot be described simply by "the value could have some possible bit pattern". LLVM and Clang are changing themselves to require special noundef attribute to perform many important optimizations that are otherwise unsound. For a concrete example of the sorts of problems this can cause, see this issue @scottmcm hit.

A bad example

#[derive(Clone, Copy)]
#[repr(C)]
struct MyDataStruct {
    a: u8,
    b: u32,
}

let my_data = MyDataStruct { a: 0, b: 42 };

// 🚨 MyDataStruct contains 3 padding bytes after `a`, which are
// uninit, therefore getting a slice that includes them is UB!
let my_data_bytes: &[u8] = transmute(&my_data);

// allocate an uninit buffer of some size
let my_buffer: MyBufferType = some_api.alloc_buffer_size(2048);

// 🚨 this is UB for the same reason, these bytes are uninit!
let buffer_as_bytes: &mut [u8] =
    slice::from_raw_parts(my_buffer.ptr(), my_buffer.size());

// 🚨 this is UB because not only are both slices invalid,
// this is not ensuring proper alignment!
buffer_as_bytes.copy_from_slice(my_data_bytes);

presser helps with this by allowing you to view raw allocated memory of some size as a "Slab" of memory and then provides safe, valid ways to copy data into that memory:

A good example

#[derive(Clone, Copy)]
#[repr(C)]
struct MyDataStruct {
    a: u8,
    b: u32,
}

let my_data = MyDataStruct { a: 0, b: 42 };

// allocate an uninit buffer of some size
let my_buffer: MyBufferType = some_api.alloc_buffer_size(2048);

// use `RawAllocation` helper to allow access to a presser `Slab`.
// alternatively, you could implement the `Slab` on your buffer type directly if that
// type is owned by your code!
let raw_allocation = presser::RawAllocation::from_raw_parts(my_buffer.ptr(), my_buffer.size());

// here we assert that we have exclusive access to the data in the buffer, and get the actual
// `Slab` to use to copy into.
let slab = unsafe { raw_allocation.borrow_as_slab(); }

// now we may safely copy `my_data` into `my_buffer`, starting at a minimum offset of 0 into the buffer
let copy_record = presser::copy_to_offset(&my_data, &mut slab, 0)?;

// note that due to alignment requirements of `my_data`, the *actual* start of the bytes of
// `my_data` may be placed at a different offset than requested. so, we check the returned
// `CopyRecord` to check the actual start offset of the copied data.
let actual_start_offset = copy_record.copy_start_offset;

Note that actually accessing the copied data is a completely separate issue which presser does not (as of now) concern itself with. BE CAREFUL!

See more in the git main docs or the released version docs.

Contribution

Contributor Covenant

We welcome community contributions to this project.

Please read our Contributor Guide for more information on how to get started. Please also read our Contributor Terms before you make any contributions.

Any contribution intentionally submitted for inclusion in an Embark Studios project, shall comply with the Rust standard licensing model (MIT OR Apache 2.0) and therefore be dual licensed as described below, without any additional terms or conditions:

License

This contribution is dual licensed under EITHER OF

at your option.

For clarity, "your" refers to Embark or any other licensee/user of the contribution.

Comments
  • Add spaces to italic parts of readme

    Add spaces to italic parts of readme

    Checklist

    • [x] I have read the Contributor Guide
    • [x] I have read and agree to the Code of Conduct
    • [x] I have added a description of my changes and why I'd like them included in the section below

    Description of Changes

    Just a small readability fix for the readme: An italic section was missing some spaces:

    anuninitpiece of memory is not simplyan arbitrary bit pattern,it is a wholly separate state

    β†’

    an uninit piece of memory is not simply an arbitrary bit pattern, it is a wholly separate state

    opened by flying-sheep 3
  • Self-audit crate with `cargo-vet`

    Self-audit crate with `cargo-vet`

    We should add a self-audit of this crate to our central audit file in https://github.com/EmbarkStudios/rust-ecosystem/blob/main/audits.toml.

    Practically all that is needed is doing a PR to that repo that adds a toml item for the latest version of presser, would be nice in the notes of the audit to describe a bit around the unsafe code in this crate, that there are no ambient capabilities or dependencies, and can say that we are using it in production. Can be quite brief though!

    See this section about what to think about for the audit: https://mozilla.github.io/cargo-vet/built-in-criteria.html#safe-to-deploy

    Self-audit/certification is fine (see cargo-vet book), but it would be wonderful if we could later also find someone external to audit it also.

    bug 
    opened by repi 1
  • Add security policy with GitHub private reporting & Bug Bounty

    Add security policy with GitHub private reporting & Bug Bounty

    This is an updated version of our standard security policy to be adapted for our repositories that use GitHub's new Private vulnerability reporting as well as our Security Bug Bounty Program, which we now use here for cargo-deny πŸŽ‰

    Just like we did for cargo-deny: https://github.com/EmbarkStudios/cargo-deny/pull/485

    opened by repi 0
  • Add `_exact` variants to copy functions

    Add `_exact` variants to copy functions

    Adds _exact variants of copy functions which ensure that the provided start_offset is where the data actually gets copied, returning an error if this would violate computed alignment requirements.

    opened by fu5ha 0
  • Fix some errors in the README

    Fix some errors in the README

    Checklist

    • [x] I have read the Contributor Guide
    • [x] I have read and agree to the Code of Conduct
    • [x] I have added a description of my changes and why I'd like them included in the section below

    Description of Changes

    Fix some errors in the README.

    opened by bjorn3 0
  • Add read helpers

    Add read helpers

    Motivated by https://github.com/Traverse-Research/gpu-allocator/pull/139, scaffolded some read-helper functions.

    These helpers are mostly all unsafe and have both semi-checked and completely unchecked variants. They are relevant in either case because they lay out in documentation exactly what the needed safety requirements are to read the given data, given that we have a properly implemented Slab, and try to remove some common footguns (alignment, size within allocation) where possible in the checked variants.

    A note for reviewers is that you can skip the copy.rs file as that is just code movement from the old lib.rs.

    @eddyb, requested your review since you helped validate presser originally and you might have some valuable input on the safety comments/requirements here.

    enhancement block-automerge 
    opened by fu5ha 1
  • Implement helper functions in terms of `[MaybeUninit<u8>]` instead of `Slab` once relevant functions are stabilized

    Implement helper functions in terms of `[MaybeUninit]` instead of `Slab` once relevant functions are stabilized

    Related to #1, but likely to come after. Requires https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#method.slice_assume_init_ref and some other MaybeUninit methods to become stable to be practical.

    enhancement tracking 
    opened by fu5ha 0
  • Change `Slab` and `RawAllocation` to use raw slices (`*mut [u8]`) when possible

    Change `Slab` and `RawAllocation` to use raw slices (`*mut [u8]`) when possible

    It would be great to be able to use these and would help with not violating miri's implementation of stacked borrows by allowing us to not narrow the borrow until needed. But, https://github.com/rust-lang/rust/issues/71146 is needed before this is possible.

    enhancement tracking 
    opened by fu5ha 0
Owner
Embark
The future belongs to the curious
Embark
Pure rust library for reading / writing DNG files providing access to the raw data in a zero-copy friendly way.

DNG-rs   A pure rust library for reading / writing DNG files providing access to the raw data in a zero-copy friendly way. Also containing code for re

apertusΒ° - open source cinema 4 Dec 1, 2022
Tool to copy things!

zp zp is a cli command to copy the contents of the source file or of the std output buffer to the clipboard. To use the zp, simply open your terminal

Gokul 26 Apr 22, 2023
lemmy-help is a emmylua parser as well as a CLI which takes that parsed tree and converts it into vim help docs.

lemmy-help is a emmylua parser as well as a CLI which takes that parsed tree and converts it into vim help docs.

Vikas Raj 117 Jan 3, 2023
A rust crate to view a structure as raw bytes (&[u8])

rawbytes A Rust crate to view a structure as a plain byte array (&[u8]). Super simple. Tiny. Zero dependencies. This is a safer interface to slice::fr

Frank Denis 4 Sep 7, 2023
Macro to customize the behavior of `?`

::custom-try Macro to customize the behavior of ? Examples use ::custom_try::custom_try; #[repr(transparent)] pub struct FfiResult { pub status_c

Daniel Henry-Mantilla 5 Dec 23, 2022
Sero is a web server that allows you to easily host your static sites without pain. The idea was inspired by surge.sh but gives you full control.

sero Lightning-fast, static web publishing with zero configuration and full control ?? Table Of Contents ?? Table Of Contents ?? Tools ❓ About The Pro

Dmitry Miasnenko 6 Nov 13, 2023
A raw implementation of Interoperable Private Attribution

Raw IPA A collaborative effort to generate a raw, but broadly functional, prototype of the Interoperable Private Attribution (IPA) proposal. The goal

Martin Thomson 1 Dec 12, 2022
Unopinionated low level API bindings focused on soundness, safety, and stronger types over raw FFI.

?? firehazard ?? Create a fire hazard by locking down your (Microsoft) Windows so nobody can escape (your security sandbox.) Unopinionated low level A

null 5 Nov 17, 2022
Use raw-window-handle 0.5 with crates that depend on 0.4.

OldHasRawWindowHandleWrapper Wrap any type that implements HasRawWindowHandle and HasRawDisplayHandle from raw-window-handle 0.5 in OldHasRawWindowHan

null 1 Nov 25, 2022
A crate that allows you to mostly-safely cast one type into another type.

A crate that allows you to mostly-safely cast one type into another type. This is mostly useful for generic functions, e.g. pub fn foo<S>(s: S) {

Bincode 3 Sep 23, 2023
zigfi is an open-source stocks, commodities and cryptocurrencies price monitoring CLI app, written fully in Rust, where you can organize assets you're watching easily into watchlists for easy access on your terminal.

zigfi zigfi is an open-source stocks, commodities and cryptocurrencies price monitoring CLI app, written fully in Rust, where you can organize assets

Aldrin Zigmund Cortez Velasco 18 Oct 24, 2022
A wrapper around the code action dump from https://mcdiamondfire.com.

DiamondFire Action Dump for Rust A wrapper around the code action dump from https://mcdiamondfire.com. This currently only provides schema types for u

null 3 Sep 17, 2022
Rust library for putting things in a grid

rust-term-grid This library arranges textual data in a grid format suitable for fixed-width fonts, using an algorithm to minimise the amount of space

Benjamin Sago 61 Nov 4, 2022
Scouty is a command-line interface (CLI) to keep an eye on substrate-based chains and hook things up

scouty is a command-line interface (CLI) to keep an eye on substrate-based chains and hook things up

TurboFlakes 15 Aug 6, 2022
Brutally simple command line app for jotting things down

jot Brutally simple command line app for jotting things down. About jot lets you get things down before you forget, without fiddling folders, naming,

Alexander Alexandrov 1 Apr 8, 2022
Giddy up! Things are going to be wild.

Jocky - For controlling your horses Current Idea The idea is essentially to have a custom directory that writes immutable segments, this means only 2

Harrison Burt 3 Jan 7, 2023
Work out how far apart things should be (very quickly)

Kern determiner Work out how far apart things should be (very quickly) kerndeterminer is a Rust-based library for determining a kern value between two

Simon Cozens 10 Oct 29, 2022
ratlab is a programming platform designed loosely for hobbyist and masochist to analyse and design stuff and things that transform our world?

ratlab A programming language developed by Quinn Horton and Jay Hunter. ratlab is a programming platform designed loosely for hobbyists and masochists

Jay 10 Sep 4, 2023
A visual canvas and virtual machine for writing assembly to build cool things. Create machines and connect them together.

Visual Assembly Canvas A highly visual assembly editor, infinite canvas for wiring blocks and machines together, bytecode virtual machine runnable nat

Phoomparin Mano 31 Oct 11, 2023