Skip to content

[Bug] "Exception: vector" crash in pattern language #2108

@berkus

Description

@berkus

Operating System

MacOS

What's the issue you encountered?

Image

This is all I get, how can I go about debugging my pattern code?

How can the issue be reproduced?

Run this script

import std.mem;
import std.io;

#pragma loop_limit 1000000

//==============================================================================
// Decompression routine
//==============================================================================

struct Subrange<auto Size> {
    u8 data[Size];
} [[hidden]];

fn decompress(auto output, u24 size) {

    // std::mem::copy_value_to_section(auto value, std::mem::Section to_section, u64 to_address);
    // std::mem::copy_value_to_section(h, decompressed, 0x0);

    // FC, FD, FE, FF - end marker (low 3 bits - uncompressed remainder to read)
    // 80 - read up to 3 bytes raw (low 3 bits), then lookup 1 byte offset ago with 1 byte len
    // 40 - read up to 3 bytes raw (low 3 bits), then lookup 2 byte offset ago with 1 byte len
    // 20 - read up to 3 bytes raw (low 3 bits), then lookup 3 byte offset ago with 1 byte len
    // otherwise - read up to 1 byte len uncompressed bytes from input

    // Initialization
    // unsigned int datapos, len, offset, inbyte, tmp1, tmp2, tmp3;
    // unsigned char *srcpos, *dstpos;
    // datapos = len = offset = inbyte = tmp1 = tmp2 = tmp3 = 0;
    //std::mem::read_unsigned($, 5);

    std::print("{}", $);
    
    u8 inbyte = std::mem::read_unsigned($, 1); $ += 1;
    std::print("=> 0x{:02x}", inbyte);
    u32 datapos = 0;

    // Decompress
    while ((!std::mem::eof()) && (inbyte < 0xFC))
    {
        std::print("=> 0x{:02x}", inbyte);
        if (inbyte & 0x80 == 0)
        {
            u8 offset_lo = std::mem::read_unsigned($, 1); $ += 1;
            u8 len = inbyte & 0x03;
            if (len != 0)
            {
                Subrange<len> input_data @ $;
                std::mem::copy_value_to_section(input_data, output, datapos);
                datapos += len;
                $ += len;
            }
            u32 dict_len = ((inbyte & 0x1C) >> 2) + 3;
            u32 offset = ((inbyte >> 5) << 8) + offset_lo + 1;
            Subrange<dict_len> dict_data @ datapos - offset in output;
            std::mem::copy_value_to_section(dict_data, output, datapos);
            datapos += dict_len;
        }
        else if (inbyte & 0x40 == 0)
        {
            u8 offset_hi = std::mem::read_unsigned($, 1); $ += 1;
            u8 offset_lo = std::mem::read_unsigned($, 1); $ += 1;
            u8 len = (offset_hi >> 6) & 0x03;
            if (len != 0)
            {
                Subrange<len> input_data @ $;
                std::mem::copy_value_to_section(input_data, output, datapos);
                datapos += len;
                $ += len;
            }
            u32 dict_len = (inbyte & 0x3F) + 4;
            u32 offset = ((offset_hi & 0x3F) * 256) + offset_lo + 1;
            Subrange<dict_len> dict_data @ datapos - offset in output;
            std::mem::copy_value_to_section(dict_data, output, datapos);
            datapos += dict_len;
        }
        else if (inbyte & 0x20 == 0)
        {
            u8 offset_hi = std::mem::read_unsigned($, 1); $ += 1;
            u8 offset_lo = std::mem::read_unsigned($, 1); $ += 1;
            u8 len_lo = std::mem::read_unsigned($, 1);
            u8 len = inbyte & 0x03;
            if (len != 0)
            {
                Subrange<len> input_data @ $;
                std::mem::copy_value_to_section(input_data, output, datapos);
                datapos += len;
                $ += len;
            }
            u32 dict_len = (((inbyte >> 2) & 0x03) * 256) + len_lo + 5;
            if (len != 0)
            {
                u32 offset = ((inbyte & 0x10) << 0x0C) + (offset_hi * 256) + offset_lo + 1;
                Subrange<dict_len> dict_data @ datapos - offset in output;
                std::mem::copy_value_to_section(dict_data, output, datapos);
                datapos += dict_len;
            }
        }
        else
        {
            u8 len = ((inbyte & 0x1F) * 4) + 4;
            if (len != 0)
            {
                Subrange<len> input_data @ $;
                std::mem::copy_value_to_section(input_data, output, datapos);
                datapos += len;
                $ += len;
            }
        }

        inbyte = std::mem::read_unsigned($, 1); $ += 1;
    }

    if (!std::mem::eof() && (datapos < size))
    {
        u8 len = inbyte & 0x03;
        if (len != 0)
        {
            Subrange<len> input_data @ $;
            std::mem::copy_value_to_section(input_data, output, datapos);
            datapos += len;
            $ += len;
        }
    }
};

//==============================================================================
// Main structure
//==============================================================================

struct Compressed {
    std::print("3 {}", $);
    u24 uncompressedSize;
    //u8 compressedContents[std::mem::size() - 5] @ 0x5;

    std::print("4 {}", $);
    std::print("uncomp size {}", uncompressedSize);
    std::mem::Section decompressed = std::mem::create_section("LZ-like decompressed");
    std::mem::set_section_size(decompressed, uncompressedSize);

    decompress(decompressed, uncompressedSize);

    u8 d[uncompressedSize] @ 0x00 in decompressed;
    builtin::hex::core::add_virtual_file(std::format("uncompressed-{}", hex::prv::get_information("file_name")), d);
    std::warning("This CRP is compressed, grab the uncompressed save from\nthe Virtual Filesystem tab and use this pattern on it again.");
};

struct Main {
    std::print("1 {}", $);
    u16 compressionMarker @ 0x0 [[hidden]];
    std::print("2 {}", $);
    if (compressionMarker == 0xFB10) {
        Compressed @ 0x2;
    }
} [[inline]];

Main m @ 0x0;

ImHex Version

1.36.2

ImHex Build Type

  • Nightly or built from sources

Installation type

brew install imhex

Additional context?

  • I am not asking to help me debug the script
  • I am asking about how to debug the script given the lack of any useful information in the exception - how to even decipher "vector"?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions