Fix panic in DetectWaf function

This commit is contained in:
shubhamrasal 2025-09-24 23:16:40 +05:30
parent 8ea5061f5e
commit afb13e2c5b

View File

@ -5,11 +5,15 @@ import (
"encoding/json" "encoding/json"
"log" "log"
"regexp" "regexp"
"runtime"
"strings"
"sync"
) )
type WafDetector struct { type WafDetector struct {
wafs map[string]waf wafs map[string]waf
regexCache map[string]*regexp.Regexp regexCache map[string]*regexp.Regexp
mu sync.RWMutex
} }
// waf represents a web application firewall definition // waf represents a web application firewall definition
@ -53,19 +57,55 @@ func NewWafDetector() *WafDetector {
} }
func (d *WafDetector) DetectWAF(content string) (string, bool) { func (d *WafDetector) DetectWAF(content string) (string, bool) {
if d == nil || d.regexCache == nil { if d == nil || d.regexCache == nil || len(content) == 0 {
return "", false return "", false
} }
d.mu.RLock()
defer d.mu.RUnlock()
// Limit content size to prevent regex catastrophic backtracking
maxContentSize := 50000 // 50KB limit
if len(content) > maxContentSize {
content = content[:maxContentSize]
}
for id, regex := range d.regexCache { for id, regex := range d.regexCache {
if regex != nil && regex.MatchString(content) { if regex == nil {
continue
}
// Safely test each regex with panic recovery
matched := func() bool {
defer func() {
if r := recover(); r != nil {
// Get stack trace and format in one line
buf := make([]byte, 4096)
n := runtime.Stack(buf, false)
stack := strings.ReplaceAll(string(buf[:n]), "\n", " | ")
log.Printf("regex panic for WAF %s: %v: %v", id, r, stack)
}
}()
return regex.MatchString(content)
}()
if matched {
return id, true return id, true
} }
} }
return "", false return "", false
} }
func (d *WafDetector) GetWAF(id string) (waf, bool) { func (d *WafDetector) GetWAF(id string) (waf, bool) {
if d == nil {
return waf{}, false
}
d.mu.RLock()
defer d.mu.RUnlock()
waf, ok := d.wafs[id] waf, ok := d.wafs[id]
return waf, ok return waf, ok
} }