Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,38 @@ vardbg replay qsort.json -v sort_vis.mp4

It is possible to generate videos live while running the debugged program, but this is discouraged because the overhead of video creation inflates execution times greatly and thus ruins profiler results. However, if profiling is not important to you, it is a valid use case.

### Step-by-Step Example (Common Pitfalls Explained)

This section provides a minimal working example and explains common errors reported by new users.

#### 1. Example Python file

Ensure the function you want to debug exists and matches the name provided in the command.

Example: `qsort.py`

```python
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[0]
left = [x for x in arr[1:] if x <= pivot]
right = [x for x in arr[1:] if x > pivot]
return quick_sort(left) + [pivot] + quick_sort(right)


### Generating and Replaying a Trace

The `replay` command requires a JSON trace file.
This file must be generated first using `vardbg run`.

```bash
vardbg run qsort.py quick_sort -o qsort.json -a 9 -a 3 -a 5 -a 1

To generate a visualization video from the trace:
vardbg replay qsort.json -v qsort.mp4


## Configuration

The video generator has many options: resolution, speed, fonts, and sizes. These options can be modified using a [TOML](https://learnxinyminutes.com/docs/toml/) config file. The [default config](https://github.com/CCExtractor/vardbg/blob/master/vardbg/output/video_writer/default_config.toml) documents the available options, which can be customized in an minimal overlay config without having to duplicate the entire config. The config can then be used by passing the `-c` argument on the command line.
Expand All @@ -90,3 +122,11 @@ Specifying the name of the variable may appear to be redundant, but there are tw
Feel free to contribute to this project! You can add features, fix bugs, or make any other improvements you see fit. We just ask that you follow the [code style guidelines](https://github.com/CCExtractor/vardbg/blob/master/CODE_STYLE.md) to keep the code consistent and coherent. These guidelines can easily be enforced before pushing with the [pre-commit](https://pre-commit.com/) framework, which can install Git pre-commit hooks with the `pre-commit install` command.

Once your contribution meets the guidelines, [open a pull request](https://github.com/CCExtractor/vardbg/compare) to make things official.


## Fuzzing

Experimental fuzzing harnesses live under `fuzz/`.
They intentionally load individual modules (e.g. `data.py`) in isolation
to avoid pulling in heavy rendering and video dependencies, keeping fuzz
targets fast and focused.
56 changes: 56 additions & 0 deletions fuzz/fuzz_frameinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
Fuzz target for FrameInfo in vardbg/data.py.
Focuses on file access, line indexing, and comment parsing.
"""


import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))

import tempfile
from types import SimpleNamespace

import importlib.util
DATA_PATH = ROOT / "vardbg" / "data.py"
spec = importlib.util.spec_from_file_location("vardbg_data", DATA_PATH)
vardbg_data = importlib.util.module_from_spec(spec)
spec.loader.exec_module(vardbg_data)
FrameInfo = vardbg_data.FrameInfo

def fuzz_input(data: bytes):
try:
# Decode fuzz data safely
text = data.decode("utf-8", errors="ignore")

# Create a temporary file with fuzzed content
with tempfile.NamedTemporaryFile(delete=False, mode="w") as f:
f.write(text)
fname = f.name

# Fake a frame-like object
fake_frame = SimpleNamespace(
f_code=SimpleNamespace(
co_name="fuzz_func",
co_filename=fname
),
f_lineno=len(text.splitlines()) or 1
)

file_cache = {}
FrameInfo(fake_frame, file_cache=file_cache)

except Exception:
# Crashes are expected in fuzzing
pass


def main():
data = sys.stdin.buffer.read()
fuzz_input(data)


if __name__ == "__main__":
main()