1- # Makefile for Python formatting in fuzzing infrastructure
2- # This file provides standardized Python code formatting rules for Zondax Ledger applications
1+ # Makefile for ledger-zxlib fuzzing
2+ # This file contains both fuzzing targets and Python formatting rules
33
4- # Configuration
4+ # === FUZZING CONFIGURATION ===
5+ # All fuzzing configuration is now managed in fuzz_local/fuzz_config.py
6+ FUZZ_DIR = fuzz_local
7+ FUZZ_BUILD_DIR = $(FUZZ_DIR ) /build
8+ FUZZ_COVERAGE_DIR = $(FUZZ_DIR ) /coverage
9+ PYTHON ?= python3
10+
11+ # === PYTHON FORMATTING CONFIGURATION ===
512BLACK_LINE_LENGTH := 120
6- # Only search in fuzzing-related directories (relative to this Makefile's location)
713FUZZING_DIR := .
8- PROJECT_FUZZ_DIR := $(shell cd ../../../ && pwd) /fuzz
9-
10- # Validate that the project fuzz directory exists
11- validate_fuzz_dir :
12- @if [ ! -d " $( PROJECT_FUZZ_DIR) " ]; then \
13- echo " ⚠️ WARNING: Project fuzz directory not found: $( PROJECT_FUZZ_DIR) " ; \
14- echo " Only formatting files in the common fuzzing library directory." ; \
15- echo " To format project-specific files, please create the 'fuzz' directory." ; \
16- fi
17-
18- # Find all Python files in fuzzing directories only
19- PYTHON_FILES := $(shell find $(FUZZING_DIR ) -name "* .py" -type f -not -path "* /.* " 2>/dev/null) \
20- $(shell if [ -d "$(PROJECT_FUZZ_DIR ) " ]; then find $(PROJECT_FUZZ_DIR ) -name "* .py" -type f -not -path "* /.* " 2>/dev/null; fi)
2114
2215# Default target
2316.PHONY : help
2417help :
25- @echo " Python Formatting Rules for Zondax Ledger Fuzzing "
18+ @echo " ledger-zxlib Fuzzing & Development Tools "
2619 @echo " "
27- @echo " Available targets:"
28- @echo " format Format Python files in fuzzing directories with Black"
29- @echo " check Check if files need formatting (no changes)"
30- @echo " install Install Black formatter"
31- @echo " clean Remove __pycache__ directories from fuzzing dirs"
32- @echo " list List Python files in fuzzing directories"
20+ @echo " === FUZZING TARGETS ==="
21+ @echo " build_fuzz Build fuzzer targets"
22+ @echo " fuzz Run all fuzzers (uses config from fuzz_config.py)"
23+ @echo " fuzz_crash Analyze any crashes found"
24+ @echo " fuzz_clean Clean fuzzing artifacts"
25+ @echo " fuzz_report Generate coverage report"
26+ @echo " fuzz_report_html Generate HTML coverage report"
27+ @echo " "
28+ @echo " === PYTHON FORMATTING ==="
29+ @echo " format Format Python files with Black"
30+ @echo " check Check if files need formatting"
31+ @echo " format_clean Remove Python cache files"
3332 @echo " "
3433 @echo " Configuration:"
35- @echo " Line length: $( BLACK_LINE_LENGTH) "
36- @echo " Fuzzing directories: $( FUZZING_DIR) $( PROJECT_FUZZ_DIR) "
34+ @echo " Edit fuzz_local/fuzz_config.py to change fuzzing parameters"
35+ @echo " "
36+ @echo " Examples:"
37+ @echo " make fuzz # Run with default config"
38+ @echo " make fuzz_report # Generate coverage report"
39+
40+ # === FUZZING TARGETS ===
41+
42+ # Check if clang is available
43+ .PHONY : check_clang
44+ check_clang :
45+ @command -v clang > /dev/null 2>&1 || { \
46+ echo " ❌ Error: clang not found. Please install clang for fuzzing." ; \
47+ echo " On macOS: brew install llvm" ; \
48+ echo " On Ubuntu: apt install clang" ; \
49+ exit 1; \
50+ }
51+ @command -v clang++ > /dev/null 2>&1 || { \
52+ echo " ❌ Error: clang++ not found. Please install clang++ for fuzzing." ; \
53+ echo " On macOS: brew install llvm" ; \
54+ echo " On Ubuntu: apt install clang" ; \
55+ exit 1; \
56+ }
57+ @echo " ✅ Clang found: $$ (clang --version | head -n1)"
58+ @echo " ✅ Clang++ found: $$ (clang++ --version | head -n1)"
59+
60+ # Build fuzzer targets
61+ .PHONY : build_fuzz
62+ build_fuzz : check_clang
63+ @echo " 🔨 Building fuzzer targets..."
64+ @mkdir -p $(FUZZ_BUILD_DIR )
65+ @cd $(FUZZ_BUILD_DIR ) && \
66+ cmake -DCMAKE_C_COMPILER=clang \
67+ -DCMAKE_CXX_COMPILER=clang++ \
68+ -DENABLE_FUZZING=ON \
69+ -DENABLE_SANITIZERS=ON \
70+ -DCMAKE_BUILD_TYPE=Debug \
71+ .. && \
72+ make -j$$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4 )
73+ @echo " ✅ Fuzzer build completed"
74+
75+ # Run fuzzers
76+ .PHONY : fuzz
77+ fuzz : build_fuzz
78+ @echo " 🚀 Starting fuzzing session..."
79+ @echo " Configuration from: $( FUZZ_DIR) /fuzz_config.py"
80+ @$(PYTHON ) $(FUZZ_DIR ) /run_local_fuzz.py
81+ @echo " 🏁 Fuzzing session completed"
82+
83+ # Analyze crashes
84+ .PHONY : fuzz_crash
85+ fuzz_crash : build_fuzz
86+ @echo " 🔍 Analyzing fuzzing crashes..."
87+ @$(PYTHON ) $(FUZZ_DIR ) /analyze_local_crashes.py
88+
89+ # Clean fuzzing artifacts
90+ .PHONY : fuzz_clean
91+ fuzz_clean :
92+ @echo " 🧹 Cleaning fuzzing artifacts..."
93+ @rm -rf $(FUZZ_BUILD_DIR )
94+ @rm -rf $(FUZZ_DIR ) /corpora
95+ @rm -rf $(FUZZ_DIR ) /logs
96+ @rm -rf $(FUZZ_DIR ) /coverage
97+ @echo " ✅ Fuzzing artifacts cleaned"
98+
99+ # Generate coverage report
100+ .PHONY : fuzz_report
101+ fuzz_report :
102+ @if [ ! -d " $( FUZZ_COVERAGE_DIR) " ] || [ -z " $$ (ls -A $( FUZZ_COVERAGE_DIR) 2>/dev/null)" ]; then \
103+ echo " Error: Coverage directory is empty. Please run the fuzzer with ENABLE_COVERAGE flag ON" ; \
104+ exit 1; \
105+ fi
106+ @command -v llvm-profdata > /dev/null 2>&1 || { \
107+ echo " ❌ Error: llvm-profdata not found. Please install LLVM tools." ; \
108+ echo " On macOS: brew install llvm" ; \
109+ echo " On Ubuntu: apt install llvm" ; \
110+ exit 1; \
111+ }
112+ @if [ -z " $$ (ls $( FUZZ_COVERAGE_DIR) /*.profraw 2>/dev/null)" ]; then \
113+ echo " ❌ Error: No .profraw files found in coverage directory." ; \
114+ echo " Please run fuzzer with coverage enabled first." ; \
115+ exit 1; \
116+ fi
117+ @llvm-profdata merge -sparse $(FUZZ_COVERAGE_DIR ) /* .profraw -o $(FUZZ_COVERAGE_DIR ) /coverage.profdata
118+ @for fuzzer in $(FUZZ_BUILD_DIR ) /fuzz-* ; do \
119+ if [ -x " $$ fuzzer" ]; then \
120+ echo " Coverage for $$ (basename $$ fuzzer):" ; \
121+ llvm-cov report $$ fuzzer -instr-profile=$(FUZZ_COVERAGE_DIR ) /coverage.profdata; \
122+ fi ; \
123+ done
124+
125+ # Generate unified HTML coverage report for all fuzzers
126+ .PHONY : fuzz_report_html
127+ fuzz_report_html :
128+ @# Check coverage directory exists and has data
129+ @if [ ! -d " $( FUZZ_COVERAGE_DIR) " ] || [ -z " $$ (ls -A $( FUZZ_COVERAGE_DIR) 2>/dev/null)" ]; then \
130+ echo " Error: Coverage directory is empty. Please run the fuzzer with ENABLE_COVERAGE flag ON" ; \
131+ exit 1; \
132+ fi
133+ @command -v llvm-profdata > /dev/null 2>&1 || { \
134+ echo " ❌ Error: llvm-profdata not found. Please install LLVM tools." ; \
135+ echo " On macOS: brew install llvm" ; \
136+ echo " On Ubuntu: apt install llvm" ; \
137+ exit 1; \
138+ }
139+ @command -v llvm-cov > /dev/null 2>&1 || { \
140+ echo " ❌ Error: llvm-cov not found. Please install LLVM tools." ; \
141+ echo " On macOS: brew install llvm" ; \
142+ echo " On Ubuntu: apt install llvm" ; \
143+ exit 1; \
144+ }
145+ @if [ -z " $$ (ls $( FUZZ_COVERAGE_DIR) /*.profraw 2>/dev/null)" ]; then \
146+ echo " ❌ Error: No .profraw files found in coverage directory." ; \
147+ echo " Please run fuzzer with coverage enabled first." ; \
148+ exit 1; \
149+ fi
150+ @# Merge all profraw files into a single profdata file
151+ @llvm-profdata merge -sparse $(FUZZ_COVERAGE_DIR ) /* .profraw -o $(FUZZ_COVERAGE_DIR ) /coverage.profdata
152+ @echo " Generating unified coverage report for all fuzzers..."
153+ @rm -rf $(FUZZ_COVERAGE_DIR ) /report_html_unified
154+ @# Generate HTML report with all fuzzer binaries
155+ @FUZZ_BINARIES=($( FUZZ_BUILD_DIR) /fuzz-* ); \
156+ if [ -e " $$ {FUZZ_BINARIES[0]}" ]; then \
157+ FIRST_BINARY=" $$ {FUZZ_BINARIES[0]}" ; \
158+ OBJECT_FLAGS=" " ; \
159+ for bin in " $$ {FUZZ_BINARIES[@]:1}" ; do \
160+ OBJECT_FLAGS=" $$ OBJECT_FLAGS -object $$ bin" ; \
161+ done ; \
162+ llvm-cov show $$ FIRST_BINARY $$ OBJECT_FLAGS \
163+ -instr-profile=$(FUZZ_COVERAGE_DIR ) /coverage.profdata \
164+ -format=html \
165+ -output-dir=$(FUZZ_COVERAGE_DIR ) /report_html_unified \
166+ -show-line-counts-or-regions \
167+ -show-instantiations \
168+ -show-expansions; \
169+ else \
170+ echo " No fuzz binaries found in $( FUZZ_BUILD_DIR) " ; \
171+ exit 1; \
172+ fi
173+ @echo " Unified HTML coverage report generated in $( FUZZ_COVERAGE_DIR) /report_html_unified"
174+ @# Open report in default browser (cross-platform)
175+ @open $(FUZZ_COVERAGE_DIR ) /report_html_unified/index.html 2> /dev/null || \
176+ xdg-open $(FUZZ_COVERAGE_DIR ) /report_html_unified/index.html 2> /dev/null || \
177+ echo " Please open manually: $( FUZZ_COVERAGE_DIR) /report_html_unified/index.html"
178+
179+ # === PYTHON FORMATTING TARGETS ===
180+
181+ # Find all Python files in fuzzing directories
182+ PYTHON_FILES := $(shell find $(FUZZING_DIR ) -name "* .py" -type f -not -path "* /.* " 2>/dev/null)
37183
38184# Install Black if not present
39- .PHONY : install
40- install :
185+ .PHONY : format_install
186+ format_install :
41187 @echo " 🔧 Installing Black Python formatter..."
42- @pip3 install black || { echo " ❌ Failed to install Black" ; exit 1; }
188+ @command -v black > /dev/null 2>&1 || \
189+ { echo " 🔧 Installing Black Python formatter…" ; \
190+ $(PYTHON ) -m pip install --user black || { echo " ❌ Failed to install Black" ; exit 1; }; }
43191 @echo " ✅ Black installed successfully"
44192
45- # Format all Python files (checks first, then formats only if needed)
193+ # Format all Python files
46194.PHONY : format
47- format : install validate_fuzz_dir
195+ format : format_install
48196 @echo " 🎨 Formatting Python files with Black..."
49- @if $(MAKE ) check; then \
197+ @if [ -z " $( PYTHON_FILES) " ]; then \
198+ echo " ⚠️ No Python files found" ; \
199+ elif black --check --quiet --line-length $(BLACK_LINE_LENGTH ) $(PYTHON_FILES ) ; then \
50200 echo " ✅ All Python files are already properly formatted - no changes needed" ; \
51201 else \
52- echo " ⚙️ Files need formatting - applying changes..." ; \
53- if [ -z " $( PYTHON_FILES) " ]; then \
54- echo " ⚠️ No Python files found" ; \
55- else \
56- black --line-length $(BLACK_LINE_LENGTH ) $(PYTHON_FILES ) && \
57- echo " ✅ All Python files formatted successfully" || \
58- { echo " ❌ Formatting failed" ; exit 1; }; \
59- fi ; \
202+ echo " ⚙️ Applying formatting changes…" ; \
203+ black --line-length $(BLACK_LINE_LENGTH ) $(PYTHON_FILES ) ; \
60204 fi
61205
62206# Check formatting without making changes
63207.PHONY : check
64- check : install validate_fuzz_dir
208+ check : format_install
65209 @echo " 🔍 Checking Python file formatting..."
66210 @if [ -z " $( PYTHON_FILES) " ]; then \
67211 echo " ⚠️ No Python files found" ; \
68212 else \
69- echo " 📁 Checking $( shell echo $( PYTHON_FILES) | wc -w) Python files:" ; \
70- for file in $( PYTHON_FILES) ; do \
71- echo " • $$ (basename $$ file)" ; \
72- done ; \
73- echo " " ; \
213+ echo " 📁 Checking $( shell echo $( PYTHON_FILES) | wc -w) Python files" ; \
74214 black --check --line-length $(BLACK_LINE_LENGTH ) $(PYTHON_FILES ) && \
75215 echo " ✅ All Python files are properly formatted" || \
76216 { echo " ❌ Some files need formatting - run 'make format'" ; exit 1; }; \
77217 fi
78218
79- # List all Python files that would be formatted
80- .PHONY : list
81- list : validate_fuzz_dir
219+ # Clean Python cache files
220+ .PHONY : format_clean
221+ format_clean :
222+ @echo " 🧹 Cleaning Python cache files..."
223+ @find $(FUZZING_DIR ) -type d -name " __pycache__" -exec rm -rf {} + 2> /dev/null || true
224+ @find $(FUZZING_DIR ) -name " *.pyc" -delete 2> /dev/null || true
225+ @find $(FUZZING_DIR ) -name " *.pyo" -delete 2> /dev/null || true
226+ @echo " ✅ Python cache files cleaned"
227+
228+ # List Python files
229+ .PHONY : format_list
230+ format_list :
82231 @echo " Python files in fuzzing directories:"
83232 @if [ -z " $( PYTHON_FILES) " ]; then \
84- echo " No Python files found in: $( FUZZING_DIR) $( PROJECT_FUZZ_DIR ) " ; \
233+ echo " No Python files found in: $( FUZZING_DIR) " ; \
85234 else \
86235 for file in $( PYTHON_FILES) ; do \
87236 echo " $$ file" ; \
88237 done ; \
89- fi
90-
91- # Clean Python cache files
92- .PHONY : clean
93- clean :
94- @echo " 🧹 Cleaning Python cache files..."
95- @find $(PYTHON_DIRS ) -type d -name " __pycache__" -exec rm -rf {} + 2> /dev/null || true
96- @find $(PYTHON_DIRS ) -name " *.pyc" -delete 2> /dev/null || true
97- @find $(PYTHON_DIRS ) -name " *.pyo" -delete 2> /dev/null || true
98- @echo " ✅ Python cache files cleaned"
99-
100- # Verify Black installation
101- .PHONY : version
102- version :
103- @echo " 🔧 Black version information:"
104- @black --version 2> /dev/null || echo " ❌ Black not installed - run 'make install'"
238+ fi
0 commit comments