<commit_before>import argparse
import ctypes
import struct

import gdb

import pwndbg.color.context as C
import pwndbg.color.memory as M
import pwndbg.commands
import pwndbg.config
import pwndbg.gdblib.typeinfo
import pwndbg.glibc
from pwndbg.color import generateColorFunction
from pwndbg.color import message
from pwndbg.commands.config import extend_value_with_default
from pwndbg.commands.config import get_config_parameters
from pwndbg.commands.config import print_row


def read_chunk(addr):
    """Read a chunk's metadata."""
    # In GLIBC versions <= 2.24 the `mchunk_[prev_]size` field was named `[prev_]size`.
    # To support both versions, change the new names to the old ones here so that
    # the rest of the code can deal with uniform names.
    renames = {
        "mchunk_size": "size",
        "mchunk_prev_size": "prev_size",
    }
    if not pwndbg.config.resolve_heap_via_heuristic:
        val = pwndbg.gdblib.typeinfo.read_gdbvalue("struct malloc_chunk", addr)
    else:
        val = pwndbg.heap.current.malloc_chunk(addr)
    return dict({renames.get(key, key): int(val[key]) for key in val.type.keys()})


def format_bin(bins, verbose=False, offset=None):
    allocator = pwndbg.heap.current
    if offset is None:
        offset = allocator.chunk_key_offset("fd")

    result = []
    bins_type = bins.pop("type")

    for size in bins:
        b = bins[size]
        count, is_chain_corrupted = None, False
        safe_lnk = False

        # fastbins consists of only single linked list
        if bins_type == "fastbins":
            chain_fd = b
            safe_lnk = pwndbg.glibc.check_safe_linking()
        # tcachebins consists of single linked list and entries count
        elif bins_type == "tcachebins":
            chain_fd, count = b
            safe_lnk = pwndbg.glibc.check_safe_linking()
        # normal bins consists of double linked list and may be corrupted (we can detect corruption)
        else:  # normal bin
            chain_fd, chain_bk, is_chain_corrupted = b

        if not verbose and (chain_fd == [0] and not count) and not is_chain_corrupted:
            continue

        if bins_type == "tcachebins":
            limit = 8
            if count <= 7:
                limit = count + 1
            formatted_chain = pwndbg.chain.format(
                chain_fd[0], offset=offset, limit=limit, safe_linking=safe_lnk
            )
        else:
            formatted_chain = pwndbg.chain.format(chain_fd[0], offset=offset, safe_linking=safe_lnk)

        if isinstance(size, int):
            size = hex(size)

        if is_chain_corrupted:
            line = message.hint(size) + message.error(" [corrupted]") + "\n"
            line += message.hint("FD: ") + formatted_chain + "\n"
            line += message.hint("BK: ") + pwndbg.chain.format(
                chain_bk[0], offset=allocator.chunk_key_offset("bk")
            )
        else:
            if count is not None:
                line = (message.hint(size) + message.hint(" [%3d]" % count) + ": ").ljust(13)
            else:
                line = (message.hint(size) + ": ").ljust(13)
            line += formatted_chain

        result.append(line)

    if not result:
        result.append(message.hint("empty"))

    return result


parser = argparse.ArgumentParser()
parser.description = "Template heap command. You can ignore this."
parser.add_argument("addr", type=int, help="Address of a chunk header.")


@pwndbg.commands.ArgparsedCommand(parser)
@pwndbg.commands.OnlyWhenRunning
@pwndbg.commands.OnlyWithResolvedHeapSyms
@pwndbg.commands.OnlyWhenHeapIsInitialized
def template_heap_command(addr):
    """Template heap command with example uses of pwndbg's heap classes."""

    # `addr` is a gdb.Value of one of several types, depending on how the user invoked this command
    # e.g. template_heap_command <address> vs. template_heap_command <symbol>

    # The `Chunk` class abstracts away many heap & gdb module internals.
    chunk = pwndbg.heap.ptmalloc.Chunk(addr)

    print(f"chunk.address: 0x{chunk.address:02x}")

    # Be aware that if a chunk field is unreadable (e.g. a fake chunk straddling an unmapped page boundary) it will be None, always check.
    if chunk.prev_size is not None:
        print(f"chunk.prev_size: 0x{chunk.prev_size:02x}")

    if chunk.size is not None:
        print(f"chunk.size: 0x{chunk.size:02x}")

    # Flags may be retrieved individually or as a dictionary of all 3.
    if chunk.non_main_arena is not None:
        print(f"chunk.non_main_arena: {chunk.non_main_arena}")

    if chunk.is_mmapped is not None:
        print(f"chunk.is_mmapped: {chunk.is_mmapped}")

    if chunk.prev_inuse is not None:
        print(f"chunk.prev_inuse: {chunk.prev_inuse}")

    if chunk.flags is not None:
        print(f"chunk.flags: {chunk.flags}")

    if chunk.fd is not None:
        print(f"chunk.fd: 0x{chunk.fd:02x}")

    if chunk.bk is not None:
        print(f"chunk.bk: 0x{chunk.bk:02x}")

<commit_msg>Remove `template_heap_command`<commit_after>import argparse
import ctypes
import struct

import gdb

import pwndbg.color.context as C
import pwndbg.color.memory as M
import pwndbg.commands
import pwndbg.config
import pwndbg.gdblib.typeinfo
import pwndbg.glibc
from pwndbg.color import generateColorFunction
from pwndbg.color import message
from pwndbg.commands.config import extend_value_with_default
from pwndbg.commands.config import get_config_parameters
from pwndbg.commands.config import print_row


def read_chunk(addr):
    """Read a chunk's metadata."""
    # In GLIBC versions <= 2.24 the `mchunk_[prev_]size` field was named `[prev_]size`.
    # To support both versions, change the new names to the old ones here so that
    # the rest of the code can deal with uniform names.
    renames = {
        "mchunk_size": "size",
        "mchunk_prev_size": "prev_size",
    }
    if not pwndbg.config.resolve_heap_via_heuristic:
        val = pwndbg.gdblib.typeinfo.read_gdbvalue("struct malloc_chunk", addr)
    else:
        val = pwndbg.heap.current.malloc_chunk(addr)
    return dict({renames.get(key, key): int(val[key]) for key in val.type.keys()})


def format_bin(bins, verbose=False, offset=None):
    allocator = pwndbg.heap.current
    if offset is None:
        offset = allocator.chunk_key_offset("fd")

    result = []
    bins_type = bins.pop("type")

    for size in bins:
        b = bins[size]
        count, is_chain_corrupted = None, False
        safe_lnk = False

        # fastbins consists of only single linked list
        if bins_type == "fastbins":
            chain_fd = b
            safe_lnk = pwndbg.glibc.check_safe_linking()
        # tcachebins consists of single linked list and entries count
        elif bins_type == "tcachebins":
            chain_fd, count = b
            safe_lnk = pwndbg.glibc.check_safe_linking()
        # normal bins consists of double linked list and may be corrupted (we can detect corruption)
        else:  # normal bin
            chain_fd, chain_bk, is_chain_corrupted = b

        if not verbose and (chain_fd == [0] and not count) and not is_chain_corrupted:
            continue

        if bins_type == "tcachebins":
            limit = 8
            if count <= 7:
                limit = count + 1
            formatted_chain = pwndbg.chain.format(
                chain_fd[0], offset=offset, limit=limit, safe_linking=safe_lnk
            )
        else:
            formatted_chain = pwndbg.chain.format(chain_fd[0], offset=offset, safe_linking=safe_lnk)

        if isinstance(size, int):
            size = hex(size)

        if is_chain_corrupted:
            line = message.hint(size) + message.error(" [corrupted]") + "\n"
            line += message.hint("FD: ") + formatted_chain + "\n"
            line += message.hint("BK: ") + pwndbg.chain.format(
                chain_bk[0], offset=allocator.chunk_key_offset("bk")
            )
        else:
            if count is not None:
                line = (message.hint(size) + message.hint(" [%3d]" % count) + ": ").ljust(13)
            else:
                line = (message.hint(size) + ": ").ljust(13)
            line += formatted_chain

        result.append(line)

    if not result:
        result.append(message.hint("empty"))

    return result


{'fraction_non_alphanumeric': 0.09979461157424188, 'fraction_numerical': 0.0055575691675727925, 'mean_word_length': 2.6354852876592005, 'pattern_counts': {'":': 14, '<': 9, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5489195', 'n_tokens_mistral': 2705, 'n_tokens_neox': 2545, 'n_words': 701}