dmc_unrar README

April 22, 2026 · View on GitHub

dmc_unrar is a dependency-free, single-file FLOSS library for unpacking and decompressing RAR archives. dmc_unrar is licensed under the terms of the GNU General Public License version 2 (or later).

Please see dmc_unrar.c for details.

Configuration defines

All compile-time configuration goes through DMC_UNRAR_* defines. Set them with -D flags or by #define-ing them before including dmc_unrar.c. Every define has a sensible default — you only need to touch them to opt out of a default capability, opt in to a defense-in-depth check, or tune a cap.

Build and integration

DefineDefaultEffect
DMC_UNRAR_HEADER_FILE_ONLYunsetWhen defined, only the header portion of dmc_unrar.c compiles. Useful for splitting the single file across a .h / .c boundary.
DMC_UNRAR_32BIT / DMC_UNRAR_64BITautodetectForce the CPU-width assumption if the autodetector misfires on an exotic target.
DMC_UNRAR_SIZE_Tuint64_tInternal size type. Override on targets where a smaller type is required.
DMC_UNRAR_OFFSET_Tint64_tInternal signed offset type. Override alongside DMC_UNRAR_SIZE_T.
DMC_HAS_LARGE_FILE_SUPPORTautodetectForce on/off support for files and archives ≥ 2 GiB. Without it, the library returns DMC_UNRAR_FILE_UNSUPPORTED_LARGE for large entries. Note: missing the UNRAR infix for historical reasons.
DMC_UNRAR_USE_FSEEKO_FTELLOautodetectForce fseeko/ftello instead of fseek/ftell for file IO. Autodetected on 32-bit macOS and glibc.

Feature toggles (opt out of default-on capabilities)

DefineDefaultEffect
DMC_UNRAR_DISABLE_STDIO0Disable all FILE* / path-based APIs. Only memory-based APIs remain.
DMC_UNRAR_DISABLE_WIN32autodetectDon't use the Win32 UTF-16 IO path. On Windows this drops path support to plain ASCII; elsewhere the flag has no effect.
DMC_UNRAR_DISABLE_MALLOC0Remove all internal malloc / realloc / free calls. Callers must then supply allocator callbacks or use only static-buffer paths.
DMC_UNRAR_DISABLE_BE32TOH_BE64TOH0Don't include <endian.h>. Needed on targets that lack it (e.g. strict C89, some non-glibc libcs).
DMC_UNRAR_DISABLE_PPMD0Drop the PPMd decoder. Entries compressed with PPMd return DMC_UNRAR_30_DISABLED_FEATURE_PPMD.
DMC_UNRAR_DISABLE_FILTERS0Drop RAR filter support. Filtered entries return DMC_UNRAR_30_DISABLED_FEATURE_FILTERS / DMC_UNRAR_50_DISABLED_FEATURE_FILTERS.

Safety and hardening

These control checks that protect apps extracting untrusted archives. REJECT_* defines are opt-in; DISABLE_* defines are opt-outs of a default-on check.

DefineDefaultEffect
DMC_UNRAR_DISABLE_HEADER_CRC_CHECK0 (i.e. enforcement on)When set, accept RAR4 block headers whose stored CRC doesn't match. Otherwise a bad CRC fails archive open with DMC_UNRAR_INVALID_DATA.
DMC_UNRAR_REJECT_NON_UTF8_PATHS0Make dmc_unrar_extract_file_to_path() reject archive names that aren't valid UTF-8. Returns DMC_UNRAR_FILE_UNSAFE_PATH. The _unsafe variant skips this check.
DMC_UNRAR_REJECT_WINDOWS_RESERVED_NAMESon under _WIN32, off elsewhere (overridable)Reject archive names whose components are unsafe on Windows: reserved device names (CON, PRN, AUX, NUL, COM1-9, LPT1-9), illegal characters (< > : " | ? * and ASCII controls), or trailing spaces/dots. Device-name checks are case-insensitive; CON.txt is rejected alongside bare CON. Returns DMC_UNRAR_FILE_UNSAFE_PATH. The _unsafe variant skips this check.
DMC_UNRAR_REJECT_OVERWRITE0Make dmc_unrar_extract_file_to_path() refuse to write when the target path already exists. Returns DMC_UNRAR_FILE_EXISTS before decompressing if the target exists up front, or during final no-replace publish if another writer creates it mid-extraction. Applies to both the safe and _unsafe variants because it concerns the caller-provided target path, not the archive name.

Per-call opt-out: dmc_unrar_extract_file_to_path_unsafe()

The safe default dmc_unrar_extract_file_to_path() runs a path-safety check on every extraction and honors the opt-in REJECT_* defines above. For the rare case where the caller has already validated the archive filename externally, or is routing output to a target path that is computed independently of archive contents (e.g. a caller-chosen name with the archive entry looked up by index), there's a sibling:

dmc_unrar_return dmc_unrar_extract_file_to_path_unsafe(
    dmc_unrar_archive *archive, dmc_unrar_size_t index,
    const char *path, dmc_unrar_size_t *uncompressed_size,
    bool validate_crc);

What it bypasses:

  • The built-in path-safety check (traversal .., absolute paths, drive prefixes like C:, UNC prefixes like //server/share, surviving backslashes).
  • DMC_UNRAR_REJECT_NON_UTF8_PATHS — an archive-name check.
  • DMC_UNRAR_REJECT_WINDOWS_RESERVED_NAMES — an archive-name check.

What it still enforces:

  • DMC_UNRAR_REJECT_OVERWRITE — this concerns the caller-provided target path, not the archive name, so both variants honor it.
  • All atomic-extraction guarantees (exclusive temp-file + publish; nothing written at path on failure).
  • All resource caps and the cancellation callback.

Rule of thumb: if you are feeding dmc_unrar_get_filename() straight into the target path, use the safe default. Use _unsafe only when you've taken responsibility for filename validation yourself.

Resource caps (archive-bomb mitigation)

All caps fire deterministically at archive open or extract time with DMC_UNRAR_INVALID_DATA when exceeded. Defaults are generous; tune lower if your workload has a narrower plausible envelope.

DefineDefaultWhat it limits
DMC_UNRAR_MAX_FILE_COUNT1,000,000Declared entries per archive.
DMC_UNRAR_MAX_FILE_SIZE16 GiBDeclared uncompressed size for any single entry.
DMC_UNRAR_MAX_TOTAL_SIZE256 GiBCumulative declared uncompressed size across all entries.
DMC_UNRAR_MAX_COMPRESSION_RATIO1000:1Per-entry uncompressed/compressed ratio. Stored entries (1:1) always pass.
DMC_UNRAR_MAX_DICT_SIZE256 MiBLZSS sliding-window size the decompressor will allocate per extraction.
DMC_UNRAR_MAX_PPMD_SIZE_MB32Archive-declared PPMd heap size (in MiB). Only enforced when the archive explicitly declares a heap size.

Tuning knobs

These trade memory for speed. Defaults are a reasonable compromise.

DefineDefaultEffect
DMC_UNRAR_ARRAY_INITIAL_CAPACITY8Initial capacity of the internal file-entry array. Higher = fewer reallocations during open; wasted memory on small archives.
DMC_UNRAR_BS_BUFFER_SIZE4096Bitstream buffer size in bytes. Must be a multiple of 8. Higher = faster, more memory.
DMC_UNRAR_HUFF_MAX_TABLE_DEPTH10Huffman direct-lookup table depth. Memory scales as 2^depth * 4 bytes; longer codes fall through to a binary tree.

Cooperative cancellation

Not a #define but worth mentioning alongside the caps: set dmc_unrar_cancel on the archive struct to a callback that the library polls at block-collect, extract, and decompressor loop points. Returning false unwinds with DMC_UNRAR_USER_CANCEL. See the archive struct definition in dmc_unrar.c for details.