Skip to content

False negative sparse mask #8

@mrexodia

Description

@mrexodia

Repro

#include <Pattern16.h>

#include <cstdint>
#include <iomanip>
#include <iostream>
#include <random>
#include <sstream>
#include <string>
#include <vector>

using u8 = std::uint8_t;

static std::string to_signature(const std::vector<u8>& pattern, const std::string& mask)
{
    std::ostringstream oss;
    for (size_t i = 0; i < mask.size(); ++i)
    {
        if (i) oss << ' ';
        if (mask[i] == 'x')
            oss << std::uppercase << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned>(pattern[i]);
        else
            oss << "??";
    }
    return oss.str();
}

static size_t reference_find_first(const std::vector<u8>& data, const std::vector<u8>& pattern, const std::string& mask)
{
    for (size_t off = 0; off + pattern.size() <= data.size(); ++off)
    {
        bool match = true;
        for (size_t i = 0; i < pattern.size(); ++i)
        {
            if (mask[i] == 'x' && data[off + i] != pattern[i]) { match = false; break; }
        }
        if (match) return off;
    }
    return static_cast<size_t>(-1);
}

int main()
{
    const std::vector<u8> pattern = {
        0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0xB8, 0x00, 0x00, 0x00,
        0xD3, 0x00, 0x2C, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x19
    };
    const std::string mask = "??x?????x?????x?x???x?x?x????x";

    const size_t data_len = 4699;
    std::vector<u8> data(data_len);

    std::mt19937 rng(0x88BEA0B2u);
    std::uniform_int_distribution<int> byte_dist(0, 255);
    for (size_t i = 0; i < data_len; ++i)
        data[i] = static_cast<u8>(byte_dist(rng));

    const size_t inject_offsets[] = {440, 684, 1023, 1388, 2011, 2750, 3301, 4096};
    for (size_t off : inject_offsets)
    {
        if (off + pattern.size() > data.size()) continue;
        for (size_t j = 0; j < pattern.size(); ++j)
            if (mask[j] == 'x') data[off + j] = pattern[j];
    }

    const std::string signature = to_signature(pattern, mask);
    const size_t expected = reference_find_first(data, pattern, mask);
    const u8* found = static_cast<const u8*>(Pattern16::scan(data.data(), data.size(), signature));
    const size_t got = found ? static_cast<size_t>(found - data.data()) : static_cast<size_t>(-1);

    std::cout << "expected=" << expected << " got=" << got << "\n";
}

Expected

  • expected=31 got=31

Actual

  • expected=31 got=18446744073709551615

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions