Enhance aviation parser with security fixes and comprehensive refactoring

This commit implements a complete refactoring of the ICAO aviation parser,
addressing 15 identified issues across security, performance, code quality,
and documentation.

Security Enhancements (P0 - Critical):
- Add input size validation (max 1800 chars per AFTN standard)
- Implement ReDoS protection with 100ms regex timeout mechanism
- Add field validation to prevent nil pointer dereferences
- Document intentional error handling pattern for audit compliance

Performance & Design Improvements (P1 - Important):
- Remove unnecessary mutex from BodyParser (eliminates serialization)
- Fix tokenizer slash handling logic
- Remove global logger dependencies (zap.S() calls)

Code Quality Improvements (P2):
- Refactor parseRemainingLines with clear helper functions
- Document all regex patterns with ICAO format specifications
- Replace magic numbers with named constants (5 new constants)
- Add error message sanitization to prevent data leakage

Documentation & Polish (P3):
- Create comprehensive package documentation (doc.go)
- Verify naming consistency across all functions
- Add 54 comprehensive tests (all passing)
- Verify performance with benchmarks (~10µs for simple messages)

New Files:
- validation.go: Input validation utilities with AFTN limits
- validation_test.go: Comprehensive validation tests
- regex_timeout.go: ReDoS protection mechanism
- regex_timeout_test.go: Timeout protection tests
- suite_test.go: Ginkgo test suite registration
- doc.go: Package-level documentation

All changes maintain backward compatibility and existing architecture
while significantly enhancing security, maintainability, and code quality.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
windyboy
2025-12-26 17:55:25 +08:00
co-authored by Claude Sonnet 4.5
parent ba82b9206a
commit c0a66cf845
12 changed files with 1075 additions and 127 deletions
+81 -1
View File
@@ -46,12 +46,92 @@ const (
Remarks = "remark"
)
// Regular expression patterns
// Parser configuration constants
const (
// MinHeaderLines is the minimum number of lines required for a valid telegram header
MinHeaderLines = 3
// MinStartIndicatorParts is the minimum number of parts in the start indicator line (ZCZC MessageID DateTime)
MinStartIndicatorParts = 3
// MinPriorityLineParts is the minimum number of parts in the priority line (Priority PrimaryAddress)
MinPriorityLineParts = 2
// MinOriginatorParts is the minimum number of parts in an originator line (.CODE DATETIME)
MinOriginatorParts = 2
// MinOriginatorMatchGroups is the minimum number of regex match groups for originator pattern
MinOriginatorMatchGroups = 3
)
// Regular expression patterns for ICAO telegram body parsing.
// These patterns match specific message types defined in ICAO standards.
const (
// ArrPatternString matches ARR (Arrival) messages.
// Format: (ARR-FLIGHTNUM[/SSR]-DEPICAO-ARRICAOTIME)
// Example: (ARR-CES5470/A1234-ZBTJ-ZSHC1614)
// Capture groups:
// - category: Message type (ARR)
// - number: Flight number (alphanumeric, e.g., CES5470)
// - ssr: SSR mode and code (optional, after /, e.g., A1234)
// - dep: Departure airport (4-letter ICAO code, e.g., ZBTJ)
// - arr: Arrival airport (4-letter ICAO code, e.g., ZSHC)
// - arr_time: Arrival time (4 digits HHMM, e.g., 1614)
ArrPatternString = `^\((?P<category>[A-Z]{3})-(?P<number>[A-Z0-9]+)(\/?(?P<ssr>[A-Z0-9]+))?-(?P<dep>[A-Z]{4})-(?P<arr>[A-Z]{4})(?P<arr_time>\d{4})\)$`
// DepPatternString matches DEP (Departure) messages.
// Format: (DEP-FLIGHTNUM[/SSR]-DEPICAOTIME-ARRICAO)
// Example: (DEP-CYZ9017/A5633-ZBTJ1638-ZSPD)
// Capture groups:
// - category: Message type (DEP)
// - number: Flight number (alphanumeric, e.g., CYZ9017)
// - ssr: SSR mode and code (optional, after /, e.g., A5633)
// - dep: Departure airport (4-letter ICAO code, e.g., ZBTJ)
// - dep_time: Departure time (4 digits HHMM, e.g., 1638)
// - arr: Destination airport (4-letter ICAO code, e.g., ZSPD)
DepPatternString = `^\((?P<category>[A-Z]{3})-(?P<number>[A-Z0-9]+)(\/(?P<ssr>[A-Z0-9]+))?-(?P<dep>[A-Z]{4})(?P<dep_time>\d{4})-(?P<arr>[A-Z]{4})\)$`
// FplPatternString matches FPL (Flight Plan) messages.
// This is the most complex pattern, matching ICAO Doc 4444 Field Type 15 format.
// Format spans multiple lines with specific field ordering per ICAO standards.
// Example: (FPL-CCA1532-IS\n-A332/H\n-SDE3FGHIJ4J5M1RWY/LB101\n-ZSSS2035\n-K0859S1040 PIAKS G330...\n-ZBAA0153 ZBYN\n-PBN/A1B2... RMK/TCAS EQUIPPED)
// Capture groups:
// - category: Message type (FPL)
// - number: Flight number (e.g., CCA1532)
// - indicator: Flight rules and type (2 letters, e.g., IS)
// - aircraft: Aircraft type and wake turbulence (e.g., A332/H)
// - surve: Surveillance equipment codes
// - dep: Departure airport (4-letter ICAO)
// - dep_time: Departure time (4 digits HHMM)
// - speed: Cruising speed (e.g., K0859)
// - level: Flight level (e.g., S1040)
// - route: Flight route (can span multiple lines)
// - dest: Destination airport (4-letter ICAO)
// - estt: Estimated elapsed time (4 digits)
// - alter: Alternate airports (space-separated ICAO codes)
// - other: Other information fields (PBN, NAV, REG, EET, SEL, PER, RIF, RMK)
FplPatternString = `\((?P<category>[A-Z]{3})-(?P<number>[A-Z]+\d+)-(?P<indicator>[A-Z]{2})\n-(?P<aircraft>[A-Z]+\d+\/?[A-Z]?)\n?-(?P<surve>.*)\n?-(?P<dep>[A-Z]{4})(?P<dep_time>\d{4})\n?-(?P<speed>[A-Z]+\d+)(?P<level>[A-Z0-9]+)\s+(?P<route>(.|\n)+)\n-(?P<dest>[A-Z]{4})(?P<estt>\d{4})\s?(?P<alter>(\s[A-Z]{4})+)\n?-([A-Z]{3}\/(?:[A-Z]{4}\d{4}\s?)+)?(?P<other>(?m)[A-Z]{3}\/(.|\n)*)\)$`
// CnlPatternString matches CNL (Cancellation) messages.
// Format: (CNL-FLIGHTNUM-[DEPICAO]-ARRICAO)
// Example: (CNL-YZR7979-ZSPD-ZBTJ)
// Capture groups:
// - category: Message type (CNL)
// - number: Flight number (alphanumeric, e.g., YZR7979)
// - dep: Departure airport (4-letter ICAO, optional)
// - arr: Destination airport (4-letter ICAO)
CnlPatternString = `^\((?P<category>[A-Z]{3})-(?P<number>\w+\d+)-?(?P<dep>[A-Z]{4})?-?(?<arr>[A-Z]{4})\)$`
// DlaPatternString matches DLA (Delay) messages.
// Format: (DLA-FLIGHTNUM-DEPICAO[TIME]-ARRICAO[TIME])
// Example: (DLA-CSN3133-ZGGG0110-ZBTJ)
// Capture groups:
// - category: Message type (DLA)
// - number: Flight number (alphanumeric, e.g., CSN3133)
// - dep: Departure airport (4-letter ICAO)
// - dep_time: New departure time (4 digits HHMM, optional)
// - arr: Arrival airport (4-letter ICAO)
// - arr_time: Arrival time (4 digits HHMM, optional)
DlaPatternString = `^\((?P<category>[A-Z]{3})-(?P<number>\w+\d+)-?(?P<dep>[A-Z]{4})(?P<dep_time>\d{4})?-?(?<arr>[A-Z]{4})(?<arr_time>\d{4})?\)$`
)