F3.Postscript (F3 v0.1.0)

Copy Markdown

The 32-byte tail of an F3 file.

Fields are little-endian, in the order fixed by F3.Format.postscript_layout/0. The magic F3 is last. This module checks the tail and the claimed sizes. It does not decode the footer and it does not verify checksums.

metadata_size and footer_size are attacker-controlled. A claim larger than max_metadata_bytes is :resource_limit and is not allocated. The default cap is 16 MiB. Pass a non-negative integer to decode/2 to use another cap for that call.

Summary

Functions

Reads and checks the postscript of an open file.

Default maximum metadata span, in bytes, for one decode/2 call.

Types

checksum_type()

@type checksum_type() :: :xxhash | {:unknown, 0..255}

compression()

@type compression() :: :uncompressed

t()

@type t() :: %F3.Postscript{
  checksum_type: checksum_type(),
  data_checksum: non_neg_integer(),
  file_size: non_neg_integer(),
  footer_compression: compression(),
  footer_offset: non_neg_integer(),
  footer_size: non_neg_integer(),
  major_version: non_neg_integer(),
  metadata_offset: non_neg_integer(),
  metadata_size: non_neg_integer(),
  minor_version: non_neg_integer(),
  schema_checksum: non_neg_integer()
}

Functions

decode(file, max)

@spec decode(F3.File.t(), non_neg_integer()) :: {:ok, t()} | {:error, F3.Error.t()}

Reads and checks the postscript of an open file.

max_metadata_bytes limits metadata_size and footer_size. Checksum type 0 is :xxhash. Any other byte is {:unknown, byte} and is not a reason to stop. Footer compression other than uncompressed is :unsupported_encoding. A file shorter than 32 bytes is :truncated. max must be a non-negative integer. This does not raise for a short file.

Examples

iex> {:ok, file} = F3.open("test/fixtures/small.f3")
iex> {:ok, post} = F3.Postscript.decode(file, F3.Postscript.max_metadata_bytes())
iex> {post.major_version, post.minor_version, post.footer_compression}
{0, 1, :uncompressed}

iex> {:ok, short} = F3.open({:memory, "no"})
iex> {:error, error} = F3.Postscript.decode(short, 32)
iex> error.category
:truncated

max_metadata_bytes()

@spec max_metadata_bytes() :: pos_integer()

Default maximum metadata span, in bytes, for one decode/2 call.

Examples

iex> F3.Postscript.max_metadata_bytes()
16_777_216