Skip to content

Error Conditions

This document specifies error conditions and handling requirements for 7z archive processing.

Error Categories

Fatal Errors

Errors that MUST abort processing:

ErrorConditionAction
InvalidSignatureSignature bytes don't matchAbort
UnsupportedVersionMajor version > 0Abort
HeaderCrcMismatchStartHeaderCRC or NextHeaderCRC invalidAbort
HeaderTruncatedNextHeaderOffset + NextHeaderSize > file sizeAbort
PathTraversalPath contains .. or is absoluteAbort or skip entry
ResourceLimitExceededAny resource limit violatedAbort

Recoverable Errors

Errors that MAY allow continued processing:

ErrorConditionOptions
DataCrcMismatchFile CRC doesn't matchWarn and continue, or abort
UnsupportedMethodUnknown compression methodSkip entry
UnknownPropertyUnknown property IDSkip property
WrongPasswordDecryption failsRequest new password
CorruptEntrySingle entry corruptedSkip entry

Warnings

Conditions that SHOULD be reported but don't require action:

WarningCondition
MinorVersionUnknownMinor version > 4
UnusedPropertyProperty with no effect
NonCanonicalEncodingNUMBER not minimally encoded
DeprecatedMethodUsing obsolete compression

Error Codes

Numeric error codes for programmatic handling:

CodeNameDescription
0OKSuccess
1ERROR_DATACorrupted data
2ERROR_MEMMemory allocation failed
3ERROR_CRCChecksum mismatch
4ERROR_UNSUPPORTEDUnsupported feature
5ERROR_PARAMInvalid parameter
6ERROR_INPUT_EOFUnexpected end of file
7ERROR_OUTPUT_EOFOutput buffer overflow
8ERROR_READRead failure
9ERROR_WRITEWrite failure
10ERROR_PROGRESSProgress callback error
11ERROR_FAILGeneral failure
12ERROR_THREADThreading error
13-15ReservedReserved for future use
16ERROR_ARCHIVEInvalid archive format
17ERROR_NO_ARCHIVENot a 7z archive
18ERROR_PASSWORDWrong or missing password
19ERROR_PATHPath validation failed
20ERROR_LIMITResource limit exceeded

Error Context

Errors SHOULD include context information:

struct Error {
    code: ErrorCode,
    message: String,
    context: ErrorContext,
}

struct ErrorContext {
    offset: Option<u64>,      // File offset where error occurred
    entry_index: Option<u32>, // Entry being processed
    entry_name: Option<String>, // Entry name if known
    property_id: Option<u8>,  // Property being parsed
    method_id: Option<u64>,   // Method causing error
}

Example Error Messages

Error: CRC mismatch
  Expected: 0x12345678
  Actual:   0x87654321
  Offset:   0x1000
  Entry:    "documents/report.pdf"

Error: Unsupported compression method
  Method ID: 0x04F71199
  Entry:     "data.bin"

Error: Path traversal detected
  Path:     "../../../etc/passwd"
  Entry:    3

Validation Sequence

Opening Archive

function open_archive(file):
    # 1. Check file size
    if file.size < 32:
        error(ERROR_NO_ARCHIVE, "File too small")

    # 2. Check signature
    signature = file.read(6)
    if signature != SIGNATURE:
        error(ERROR_NO_ARCHIVE, "Invalid signature")

    # 3. Check version
    major = file.read_byte()
    minor = file.read_byte()
    if major > 0:
        error(ERROR_UNSUPPORTED, "Unsupported major version")
    if minor > 4:
        warn("Unknown minor version")

    # 4. Validate start header CRC
    start_crc = file.read_u32()
    header_data = file.read(20)
    if crc32(header_data) != start_crc:
        error(ERROR_CRC, "Start header CRC mismatch")

    # 5. Parse header offsets
    next_offset = parse_u64(header_data[0:8])
    next_size = parse_u64(header_data[8:16])
    next_crc = parse_u32(header_data[16:20])

    # 6. Validate bounds
    if 32 + next_offset + next_size > file.size:
        error(ERROR_ARCHIVE, "Header offset out of bounds")

    # 7. Read and validate next header
    file.seek(32 + next_offset)
    header_bytes = file.read(next_size)
    if crc32(header_bytes) != next_crc:
        error(ERROR_CRC, "Next header CRC mismatch")

    return parse_header(header_bytes)

Extracting Entry

function extract_entry(archive, entry, output):
    try:
        # Validate path
        if not is_safe_path(entry.path):
            error(ERROR_PATH, "Unsafe path")

        # Check method support
        for coder in entry.folder.coders:
            if not is_supported(coder.method_id):
                error(ERROR_UNSUPPORTED, "Unsupported method")

        # Decompress
        data = decompress(entry)

        # Verify CRC
        if entry.crc is not None:
            if crc32(data) != entry.crc:
                error(ERROR_CRC, "Entry CRC mismatch")

        # Write output
        write_file(output, data, entry.attributes)

    except PasswordRequired:
        # Request password and retry
        raise

    except Exception as e:
        # Log and optionally continue
        log_error(e, entry)
        if strict_mode:
            raise

Password Error Handling

Detection Methods

  1. PKCS#7 padding validation:

    • After AES decryption, check padding bytes
    • Invalid padding → likely wrong password
  2. Decompression failure:

    • After decryption, decompression fails
    • Invalid compressed data → wrong password
  3. CRC mismatch:

    • Decompression succeeds but CRC fails
    • Data corruption or wrong password

Response

function handle_password_error(error_type):
    # Don't reveal which check failed
    if error_type in [PADDING_INVALID, DECOMPRESS_FAIL, CRC_MISMATCH]:
        raise PasswordError("Wrong password or corrupted data")

    raise error_type  # Other errors pass through

Recovery Strategies

Partial Extraction

For large archives with some corrupted entries:

function extract_with_recovery(archive, output_dir):
    results = []

    for entry in archive.entries:
        try:
            extract_entry(entry, output_dir)
            results.append((entry, SUCCESS))
        except CrcMismatch as e:
            # Extract anyway, mark as potentially corrupt
            results.append((entry, EXTRACTED_WITH_WARNING))
            log_warning(e)
        except UnsupportedMethod:
            # Skip entry
            results.append((entry, SKIPPED))
            log_info("Skipped unsupported entry")
        except FatalError as e:
            # Cannot continue
            raise

    return results

Archive Recovery

For severely corrupted archives:

  1. Scan for valid signature
  2. Attempt to parse header
  3. Extract files with valid CRCs
  4. Report unrecoverable entries

Cleanup on Error

When errors occur during extraction:

  1. Close open file handles
  2. Delete partially written files
  3. Remove empty directories created
  4. Report cleanup actions
function safe_extract(archive, output_dir):
    created_files = []
    created_dirs = []

    try:
        for entry in archive:
            if entry.is_directory:
                mkdir(output_dir / entry.path)
                created_dirs.append(entry.path)
            else:
                extract_file(entry, output_dir)
                created_files.append(entry.path)

    except Exception as e:
        # Cleanup on failure
        for file in reversed(created_files):
            try_delete(output_dir / file)
        for dir in reversed(created_dirs):
            try_rmdir(output_dir / dir)
        raise

See Also

Released under MIT OR Apache-2.0 License