Skip to content

feat(parser): add fuzz testing and fix circular reference infinite loops#41

Merged
erraggy merged 4 commits intomainfrom
feat/fuzz-testing-parser
Nov 26, 2025
Merged

feat(parser): add fuzz testing and fix circular reference infinite loops#41
erraggy merged 4 commits intomainfrom
feat/fuzz-testing-parser

Conversation

@erraggy
Copy link
Copy Markdown
Owner

@erraggy erraggy commented Nov 26, 2025

Summary

Adds comprehensive fuzz testing to the parser package and fixes two critical infinite loop bugs discovered during fuzzing.

Changes

Fuzz Testing Infrastructure

  • New: parser/parser_fuzz_test.go with comprehensive seed corpus

    • 19 seed inputs covering OAS 2.0, 3.0, 3.1, edge cases, and malformed data
    • Tests ParseBytes with full reference resolution and validation enabled
    • Fuzzer discovered 171 interesting inputs in 10 seconds with no crashes
  • Enhanced: Makefile with test-fuzz-parse target

    • Configurable duration via FUZZ_TIME (default: 1m30s)
    • Optional log file output via FUZZ_LOG=1
    • Excludes fuzz tests from regular test runs for fast CI/CD
  • Updated: .gitignore to exclude fuzz log files

Bug Fixes

1. Circular Self-References (Infinite Loop)

  • Issue: Parser hung indefinitely when schemas reference themselves (e.g., Node.next -> #/components/schemas/Node)
  • Root Cause: Reference resolution didn't track refs in the current call stack, allowing infinite expansion
  • Fix: Added resolving map in RefResolver to detect circular refs during expansion
  • Test: TestCircularSelfReferenceInResolve validates the fix
  • Impact: Parser now gracefully handles legitimate circular schemas without hanging

2. Root Document References (Infinite Loop)

  • Issue: Parser hung when $ref: "#" (document root) appeared anywhere in spec
  • Root Cause: Resolving # creates infinite expansion (document contains itself)
  • Fix: Skip resolving # and #/ refs entirely to prevent infinite loops
  • Test: TestRefToDocumentRoot validates the fix
  • Impact: Parser handles pathological cases discovered by fuzzer

3. Marshal Failures (Stack Overflow)

  • Issue: YAML marshaler stack overflow when re-marshaling partially resolved circular structures
  • Root Cause: After ref resolution, some circular structures can't be marshaled back to YAML
  • Fix: Gracefully fall back to original data if marshaling fails, add warning
  • Impact: Parser no longer crashes on complex circular reference patterns

Testing

Fuzz Testing Results

FUZZ_TIME=10s make test-fuzz-parse
# Result: 171 new interesting inputs, 0 crashes, 0 hangs

Regular Tests

make check
# All tests pass in 0.268s (excluding fuzz tests)

New Test Coverage

  • TestCircularSelfReferenceInResolve - Self-referencing schemas
  • TestRefToDocumentRoot - Root document references
  • FuzzParseBytes - Automated fuzz testing with seed corpus

Usage

# Regular tests (fast, excludes fuzz)
make test

# Run fuzz test for 1m30s (default)
make test-fuzz-parse

# Custom duration
FUZZ_TIME=10m make test-fuzz-parse

# Save output to timestamped log
FUZZ_LOG=1 make test-fuzz-parse

# Clean up fuzz logs
make bench-clean

Performance Impact

  • Regular tests: No performance impact - fuzz tests excluded by default
  • Fuzz test corpus: Fast - 19 seeds run in ~0.3s when included
  • Parser runtime: Minimal - circular ref detection adds simple map lookups

Breaking Changes

None. All changes are backward compatible.

Checklist

  • Code formatted with go fmt
  • All tests pass (make check)
  • New functionality has test coverage
  • Fuzz testing validates robustness
  • No performance regressions

🤖 Generated with Claude Code

Add comprehensive fuzz testing for the parser package and fix two critical
infinite loop bugs discovered during fuzzing.

## Fuzz Testing
- Add FuzzParseBytes test with 19 seed corpus entries covering OAS 2.0, 3.0,
  3.1, edge cases, and malformed inputs
- Add test-fuzz-parse Makefile target with configurable duration and optional
  log file output (FUZZ_TIME and FUZZ_LOG environment variables)
- Exclude fuzz tests from regular test runs to maintain fast CI/CD performance

## Bug Fixes
1. **Circular self-references**: Fixed infinite loop when schema references
   itself (e.g., Node.next -> Node). Added resolving map to track refs in the
   current call stack.

2. **Root document references**: Fixed infinite loop when $ref points to
   document root ("#" or "#/"). These refs are now skipped to prevent infinite
   expansion.

3. **Marshal failures**: Added graceful fallback when YAML marshaling fails
   after partial reference resolution, preventing stack overflow errors.

## Test Coverage
- Add TestCircularSelfReferenceInResolve for self-referencing schemas
- Add TestRefToDocumentRoot for root document references
- Fuzzer discovered 171 interesting inputs in 10s with no crashes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Nov 26, 2025

Pull Request Review: Fuzz Testing & Circular Reference Fixes

I've completed a thorough review of PR #41. This is an excellent contribution that addresses critical robustness issues discovered through fuzz testing. Here's my detailed feedback:


Strengths

1. Critical Bug Fixes

The PR fixes two severe infinite loop bugs that could cause production systems to hang:

  • Circular Self-References (parser/resolver.go:227-236) - The new resolving map correctly tracks refs in the current call stack, preventing infinite expansion of legitimate circular schemas (e.g., linked lists, tree nodes).
  • Document Root References (parser/resolver.go:221-225) - Properly handles pathological $ref: "#" cases by skipping resolution entirely.

Both fixes are architecturally sound and align with the OpenAPI spec's allowance for circular references.

2. Excellent Fuzz Testing Infrastructure

The new parser_fuzz_test.go demonstrates best practices:

  • Comprehensive seed corpus (19 seeds) covering valid/invalid OAS 2.0/3.0/3.1, edge cases, and malformed inputs
  • Real-world test files from testdata/ ensure fuzzer understands valid structures
  • Edge case coverage includes empty input, malformed YAML/JSON, unicode, deep nesting, null values
  • Clear documentation explaining the fuzzer's purpose and what it validates

The fuzzer already proved its value by discovering the bugs it fixes!

3. Graceful Fallback Handling

The marshal failure fallback (parser/parser.go:428-432) is well-designed:

  • Falls back to original data when re-marshaling fails (circular refs that can't serialize)
  • Adds a clear warning to result.Warnings
  • Prevents crashes while maintaining functionality

4. Strong Test Coverage

Both new regression tests (TestCircularSelfReferenceInResolve, TestRefToDocumentRoot) are thorough:

  • Test the actual bug scenarios discovered by fuzzing
  • Validate that parsing completes without hanging
  • Verify document structure is preserved
  • Include clear comments explaining the issue

5. Makefile Integration

The test-fuzz-parse target is well-thought-out:

  • Configurable duration via FUZZ_TIME
  • Optional logging via FUZZ_LOG=1
  • Helpful output with usage instructions
  • Properly integrated with bench-clean

6. Test Isolation

The regex pattern -run='Test[^F]|TestF[^u]' successfully excludes fuzz tests from regular CI runs, keeping builds fast while allowing manual fuzz testing.


🔍 Minor Issues & Suggestions

1. Regex Pattern Complexity

Location: Makefile:23,25

The pattern 'Test[^F]|TestF[^u]' is clever but potentially fragile:

  • It excludes tests starting with TestF followed by u (i.e., FuzzParseBytes)
  • However, it would incorrectly include tests named TestFile, TestFormat, etc.
  • It would incorrectly exclude tests like TestFail

Recommendation: Use a more explicit pattern:

-run='Test[^F]|TestF[^uz]'  # Exclude TestFu* and TestFz*

Or even better, explicitly exclude fuzz tests:

-run='Test' -skip='Fuzz'

The -skip flag is clearer and more maintainable.

2. Defer in Loop Context

Location: parser/resolver.go:236

The defer statement is inside a conditional within a loop:

if r.resolving[ref] {
    return nil
}
r.resolving[ref] = true
defer func() { delete(r.resolving, ref) }()

While this is correct (the defer runs when the function returns, not when the loop iteration ends), it's worth noting for code reviewers. The pattern is fine, but consider adding a comment if this is a common point of confusion.

3. Potential for Enhanced Error Messages

Location: parser/parser.go:432

The warning message is good, but could be more actionable:

result.Warnings = append(result.Warnings, 
    fmt.Sprintf("Warning: Could not re-marshal document after reference resolution (likely due to circular references): %v. Using original document structure.", err))

Suggestion: Add guidance about implications:

fmt.Sprintf("Warning: Could not re-marshal document after reference resolution (likely due to circular references): %v. Using original document structure. Some references may not be fully resolved.", err)

4. Test Assertion Could Be Stronger

Location: parser/resolver_test.go:568-572

The test verifies the $ref is preserved, but doesn't verify the circular ref handling mechanism:

if mediaType.Schema.Ref == "" {
    t.Error("Expected $ref to be preserved (not resolved)")
}

Suggestion: Consider adding a test that verifies the parser doesn't hang with a timeout:

done := make(chan bool)
go func() {
    _, _ = ParseBytes(input, true, true)
    done <- true
}()
select {
case <-done:
    // Success
case <-time.After(5 * time.Second):
    t.Fatal("Parser hung on circular reference")
}

However, this may be overkill since the test would simply hang CI if it failed.


🔒 Security Analysis

No New Vulnerabilities Introduced

  • The resolving map is properly managed with defer cleanup
  • No unbounded allocations or resource leaks
  • Circular reference detection prevents DoS via infinite loops
  • Fallback to original data is safe (no data injection risk)

Security Improvements

This PR fixes a DoS vulnerability where malicious OAS files with circular references could cause the parser to hang indefinitely.


Performance Considerations

Minimal Overhead

  • The resolving map adds O(1) lookups per reference resolution
  • Memory overhead is minimal (one map entry per active ref in call stack)
  • Regular tests exclude fuzz tests, maintaining fast CI

Fuzz Test Performance

  • 19 seed corpus entries run in ~0.3s when included
  • Fuzzer found 171 interesting inputs in 10 seconds with no crashes
  • Good fuzzer efficiency indicates well-structured code

📋 Test Coverage Assessment

Comprehensive Coverage

  • ✅ Fuzz testing with diverse inputs
  • ✅ Regression tests for both infinite loop bugs
  • ✅ Edge cases (empty input, malformed data, unicode)
  • ✅ Integration testing (parse → validate with refs)

Suggested Additions (Optional)

Consider adding a benchmark to track performance impact:

func BenchmarkParseCircularRefs(b *testing.B) {
    input, _ := os.ReadFile("../testdata/circular-schema.yaml")
    for b.Loop() {
        _, _ = ParseBytes(input, true, true)
    }
}

🎯 Alignment with CLAUDE.md

Follows Repository Guidelines

  • ✅ Uses package-level constants where appropriate
  • ✅ Comprehensive test coverage (positive, negative, edge cases)
  • ✅ Uses Go 1.24+ for b.Loop() pattern (noted for future benchmarks)
  • ✅ Proper error handling and graceful degradation
  • ✅ Clear comments explaining complex logic
  • ✅ No over-engineering - fixes are focused and minimal

🏁 Final Recommendation

APPROVE with minor suggestions

This PR is production-ready and should be merged. The critical bug fixes are well-implemented, the fuzz testing infrastructure is excellent, and the test coverage is comprehensive.

Before Merge:

  1. ✅ All CI checks should pass (pending verification)
  2. ⚠️ Consider changing the test exclusion regex to -skip='Fuzz' for clarity
  3. ✅ Verify no performance regressions with make bench (appears fine)

Post-Merge (Optional):

  • Consider adding benchmarks for circular ref handling
  • Consider expanding fuzz testing to other packages (validator, joiner, converter)

📊 Summary Metrics

Metric Status
Code Quality ⭐⭐⭐⭐⭐ Excellent
Test Coverage ⭐⭐⭐⭐⭐ Comprehensive
Security ⭐⭐⭐⭐⭐ Fixes DoS, no new issues
Performance ⭐⭐⭐⭐⭐ Minimal overhead
Documentation ⭐⭐⭐⭐☆ Good (could enhance error messages)

Overall: 5/5 - Excellent work! 🚀


Review performed using Claude Code with gopls-mcp integration for static analysis and CLAUDE.md compliance checking.

Address minor issues from claude-code-review bot feedback:

1. **Test exclusion pattern**: Replace complex regex with clearer -skip='Fuzz'
   flag for excluding fuzz tests from regular test runs. More maintainable and
   won't accidentally exclude tests like TestFile or TestFormat.

2. **Enhanced warning message**: Add note about potential incomplete reference
   resolution when marshal fallback occurs, giving users better context about
   implications.

3. **Defer clarity**: Add comment explaining that defer runs at function
   return, not loop iteration end, which is the correct behavior for tracking
   refs across the entire call stack depth.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Nov 26, 2025

PR Review: Fuzz Testing and Circular Reference Fixes

Summary

This PR adds comprehensive fuzz testing infrastructure and fixes three critical bugs that caused infinite loops and stack overflows. The implementation is excellent overall, with high-quality test coverage and thoughtful error handling.

Strengths

1. Excellent Bug Fixes

  • Circular self-references (resolver.go:227-238): The resolving map correctly tracks the call stack to detect cycles
  • Document root references (resolver.go:221-225): Smart catch for ref # and ref #/ preventing infinite recursion
  • Marshal failure handling (parser.go:428-432): Graceful fallback with appropriate warning

2. Comprehensive Fuzz Testing

  • Well-designed seed corpus covering OAS 2.0, 3.0, 3.1, edge cases, malformed inputs
  • Proper use of f.Add() for corpus seeding
  • Good inline edge cases (empty input, invalid YAML/JSON, deeply nested, unicode, null values)

3. Strong Test Coverage

  • TestCircularSelfReferenceInResolve tests legitimate circular schemas
  • TestRefToDocumentRoot tests pathological fuzzer-discovered case
  • Both verify correct parsing without hangs

4. Good Makefile Integration

  • Fuzz tests excluded from regular runs for fast CI/CD
  • Configurable duration via FUZZ_TIME
  • Optional log file output

Issues and Recommendations

Issue 1: Defer Comment Clarity (resolver.go:237-238)
The inline comment suggests loop context but defer is placed before the loop at line 267. Placement is correct but comment is confusing.

  • Recommendation: Clarify comment about when cleanup occurs

Issue 2: Fuzz Test Could Exercise More Code Paths
Current code only tests one configuration (resolveRefs=true, validateStructure=true).

  • Recommendation: Test all four flag combinations to maximize coverage
  • Impact: Medium - could discover bugs in less-tested paths

Issue 3: TestRefToDocumentRoot Over-Validates Structure
Test has 36 lines of nested validation to verify one assertion. Fragile and verbose.

  • Recommendation: Simplify by combining nil checks
  • Impact: Low - maintainability improvement

Security Analysis

No security concerns identified. Fixes properly handle:

  • Infinite loops from circular references
  • Stack overflow from deep recursion
  • Memory/resource exhaustion limits still apply

Performance Analysis

Impact: Minimal

  • Regular tests: No impact (fuzz excluded)
  • Parser runtime: Negligible (O(1) map lookups)
  • Memory: ~24 bytes per entry (temporary, cleaned via defer)

Test Coverage

Excellent coverage of new functionality. Meets all CLAUDE.md requirements.

Final Recommendation

APPROVE with minor suggestions

Fixes are correct, well-tested, and follow best practices. Issues are minor and non-blocking.

Suggested action items:

  1. High priority: Clarify defer comment
  2. Medium priority: Expand fuzz test flag combinations
  3. Low priority: Simplify TestRefToDocumentRoot

Excellent work!

erraggy and others added 2 commits November 25, 2025 23:32
Add the two fuzz corpus files discovered during fuzzing that triggered the
infinite loop bugs. These serve as regression tests and run automatically
during normal test execution.

- 1183bda38794b4b0: Circular self-reference (Node.next -> Node)
- 86518b4cae690792: Root document reference ($ref: "#")

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Address all three issues from the latest claude-code-review feedback:

1. **Defer comment clarity (resolver.go:234-236)**: Rewrote comment to
   explicitly reference the return points (lines 263 and 269) where defer
   cleanup occurs, removing confusion about loop context.

2. **Fuzz test flag combinations (parser_fuzz_test.go:73-85)**: Added
   detailed comment explaining why we only test one flag combination
   (true, true) - testing all 4 would multiply test time by 4x (76 tests
   instead of 19). Other combinations are well-covered by unit tests.

3. **Test validation simplification (resolver_test.go:537-553)**: Reduced
   TestRefToDocumentRoot from 36 lines to 17 by combining nil checks into
   compound conditions. More maintainable and equally clear.

4. **Test exclusion specificity (Makefile:23,25)**: Changed from generic
   -skip='Fuzz' to explicit -skip='FuzzParseBytes' as suggested. Simpler
   and more precise until there's a need for flexibility.

All changes maintain functionality while improving clarity and maintainability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Nov 26, 2025

Codecov Report

❌ Patch coverage is 77.77778% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.64%. Comparing base (524a7cb) to head (9665760).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
parser/parser.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #41      +/-   ##
==========================================
+ Coverage   55.31%   55.64%   +0.33%     
==========================================
  Files          30       30              
  Lines        6472     6480       +8     
==========================================
+ Hits         3580     3606      +26     
+ Misses       2222     2215       -7     
+ Partials      670      659      -11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Nov 26, 2025

Code Review - PR #41: Fuzz Testing and Circular Reference Fixes

Summary

This is an excellent PR that adds robust fuzz testing infrastructure and fixes critical infinite loop bugs discovered through fuzzing. The implementation is well-designed, thoroughly tested, and follows best practices. ✅


🎯 Strengths

1. Bug Fixes Are Critical and Well-Implemented

The PR fixes three serious bugs that could cause production hangs:

  • Circular self-references: The resolving map tracks refs in the current call stack, preventing infinite expansion (resolver.go:227-238)
  • Document root refs: Special handling for $ref: "#" prevents infinite recursion (resolver.go:221-225)
  • Marshal failures: Graceful fallback with warning prevents crashes (parser.go:428-432)

All three fixes are clean, minimal, and well-commented. The defer cleanup pattern for resolving is textbook Go. 👍

2. Fuzz Testing Implementation is Excellent

The fuzz test (parser_fuzz_test.go) demonstrates strong testing practices:

  • Comprehensive seed corpus: 19 diverse seeds covering valid/invalid inputs, edge cases, malformed data
  • Good documentation: Clear comments explain the fuzzer's purpose and design decisions
  • Pragmatic approach: Tests only (true, true) flag combination to avoid 4x slowdown, with clear rationale (lines 80-83)
  • Real-world value: Already discovered 171 interesting inputs and 3 bugs

3. Makefile Integration is Well-Designed

The test-fuzz-parse target is production-ready:

  • Configurable duration via FUZZ_TIME with sensible default (1m30s)
  • Optional logging via FUZZ_LOG=1 with timestamped files
  • Helpful output showing corpus location and re-run instructions
  • Proper exclusion from regular test runs to keep CI fast

4. Test Coverage is Comprehensive

Two new regression tests ensure the bugs stay fixed:

  • TestCircularSelfReferenceInResolve: Validates circular ref handling
  • TestRefToDocumentRoot: Validates root ref handling

Both tests verify the exact inputs that caused hangs, preventing regressions.


🔍 Issues Found

⚠️ Issue 1: Potential Data Loss with Silent Fallback (Medium Priority)

Location: parser.go:428-432

Problem: When YAML marshaling fails after reference resolution, the code silently falls back to the original data and adds a warning. This could cause unexpected behavior where users think refs are resolved but they're not.

Current behavior:

parseData, err = yaml.Marshal(rawData)
if err \!= nil {
    parseData = data  // Silent fallback to original
    result.Warnings = append(result.Warnings, "...")
}

Recommendation: Consider returning an error instead of silently falling back, or at minimum:

  1. Add a field to ParseResult like RefsPartiallyResolved bool to inform callers
  2. Make the warning more prominent (e.g., prefix with "CRITICAL:" or use a structured warnings system)
  3. Document this behavior in the function's godoc

Rationale: Silent data transformations can lead to subtle bugs in downstream code that expects refs to be resolved.


Issue 2: Typo in Fuzz Corpus (Low Priority - Cosmetic)

Location: parser/testdata/fuzz/FuzzParseBytes/1183bda38794b4b0:2

The fuzzer-generated input contains typos:

  • CicularCircular
  • camponentscomponents
  • voluevalue

Recommendation: This is actually good - the fuzzer is testing malformed inputs! However, for clarity, consider adding a comment in the test explaining that these corpus files are fuzzer-generated and intentionally contain variations/typos.


💡 Issue 3: Missing Benchmark for Reference Resolution (Low Priority - Enhancement)

Context: The PR adds new code paths in resolveRefsRecursive (circular detection, root ref detection). No benchmark exists to track the performance impact.

Recommendation: Add a benchmark like:

func BenchmarkParseWithCircularRefs(b *testing.B) {
    input := []byte(`...`) // circular ref document
    for b.Loop() {
        ParseBytes(input, true, true)
    }
}

This would:

  1. Document the expected performance baseline
  2. Catch future regressions
  3. Follow the project's emphasis on performance tracking (see CLAUDE.md)

🔒 Security Considerations

No New Security Issues

  • The circular ref detection prevents DoS via infinite loops (security improvement)
  • Depth limits (MaxRefDepth) already prevent stack overflow
  • No new external input handling or unsafe operations

👍 Follows Security Best Practices

  • Uses safe recursion with depth limits
  • Handles untrusted fuzzer inputs without crashes
  • No panics, all errors handled gracefully

📊 Performance Considerations

Minimal Impact

  • Circular detection adds simple map lookups: O(1) per ref
  • No changes to hot paths when ResolveRefs=false
  • Fuzz tests excluded from regular runs via -skip='FuzzParseBytes'

💡 Future Optimization Opportunity

The resolving map allocates/deletes on every ref. For documents with hundreds of refs, consider:

// Pre-allocate with capacity hint
resolving: make(map[string]bool, 32)

This is a minor micro-optimization and not required for this PR.


🧪 Test Coverage Assessment

Excellent Coverage

  • Fuzz test with 19 diverse seed inputs
  • 2 new regression tests for discovered bugs
  • Tests cover both success paths and error handling
  • Integration with existing test suite

📋 Coverage Checklist

  • Exported functions tested
  • Error paths tested
  • Edge cases covered (circular refs, root refs, marshal failures)
  • Integration tests present
  • Fuzz testing for robustness

📝 Code Quality Assessment

Excellent Quality

  • Clear comments: All new code is well-documented
  • Idiomatic Go: Proper use of defer, error handling, maps
  • Consistent style: Matches existing codebase patterns
  • Good separation of concerns: Fuzz test in separate file

Minor Suggestions:

  1. resolver.go:234-236: The comment about defer cleanup is helpful, but line numbers 263 and 269 may become stale. Consider:

    // Mark this ref as being resolved. The defer cleanup runs when
    // resolveRefsRecursive returns, maintaining correct state across
    // all recursive calls.
  2. parser_fuzz_test.go:51: The long string generation could document why 10000 bytes:

    []byte(`openapi: "`+string(make([]byte, 10000))+`"`),  // 10KB string to test large value handling

🎯 Overall Assessment

Category Rating Notes
Code Quality ⭐⭐⭐⭐⭐ Clean, idiomatic, well-documented
Bug Fixes ⭐⭐⭐⭐⭐ Critical bugs fixed correctly
Test Coverage ⭐⭐⭐⭐⭐ Comprehensive + fuzz testing
Performance ⭐⭐⭐⭐⭐ Minimal impact, well-optimized
Security ⭐⭐⭐⭐⭐ Fixes DoS vulnerability
Documentation ⭐⭐⭐⭐☆ Good, could add godoc note about fallback behavior

🚀 Recommendation

APPROVE with minor suggestions

This PR is ready to merge. The identified issues are minor and don't block merging:

The fuzz testing infrastructure is a significant quality improvement that will pay dividends in finding future bugs. The bug fixes prevent critical hangs that could affect production users.

Suggested follow-up PR (optional, not blocking):

  1. Add RefsPartiallyResolved bool to ParseResult
  2. Add benchmark for circular ref performance
  3. Document fallback behavior in godoc

🎓 Learning Opportunity

This PR demonstrates excellent engineering practices:

  1. Using fuzz testing to discover real bugs
  2. Adding regression tests for fuzzer discoveries
  3. Minimal, targeted fixes with clear comments
  4. Thoughtful integration with CI/CD (fuzz tests separate)

Great work! 🎉

@erraggy
Copy link
Copy Markdown
Owner Author

erraggy commented Nov 26, 2025

Codecov Report

❌ Patch coverage is 77.77778% with 2 lines in your changes missing coverage. Please review. ✅ Project coverage is 55.64%. Comparing base (524a7cb) to head (9665760).

Files with missing lines Patch % Lines
parser/parser.go 0.00% 2 Missing ⚠️
Additional details and impacted files

@@            Coverage Diff             @@
##             main      #41      +/-   ##
==========================================
+ Coverage   55.31%   55.64%   +0.33%     
==========================================
  Files          30       30              
  Lines        6472     6480       +8     
==========================================
+ Hits         3580     3606      +26     
+ Misses       2222     2215       -7     
+ Partials      670      659      -11     

☔ View full report in Codecov by Sentry. 📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:

The 2 missing lines were actually utilized in a fuzz test that detected an infinite loop. There is more than sufficient coverage with this PR.

@erraggy erraggy merged commit 71bbea8 into main Nov 26, 2025
8 checks passed
@erraggy erraggy deleted the feat/fuzz-testing-parser branch November 26, 2025 07:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant