fix: 修复解压炸弹漏洞和goroutine泄漏
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f43b06e13d
commit
76a5eaaad9
@ -62,6 +62,7 @@ type minimaxService struct {
|
|||||||
jobs map[string]*ImageGenerationJob
|
jobs map[string]*ImageGenerationJob
|
||||||
jobsLock sync.RWMutex
|
jobsLock sync.RWMutex
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
stopCh chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMinimaxService 创建 MiniMax 服务
|
// NewMinimaxService 创建 MiniMax 服务
|
||||||
@ -70,6 +71,7 @@ func NewMinimaxService(cfg *config.AssetConfig) MinimaxService {
|
|||||||
config: cfg,
|
config: cfg,
|
||||||
jobs: make(map[string]*ImageGenerationJob),
|
jobs: make(map[string]*ImageGenerationJob),
|
||||||
client: &http.Client{Timeout: 120 * time.Second},
|
client: &http.Client{Timeout: 120 * time.Second},
|
||||||
|
stopCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
go svc.cleanupExpiredJobs()
|
go svc.cleanupExpiredJobs()
|
||||||
return svc
|
return svc
|
||||||
@ -246,10 +248,21 @@ func (s *minimaxService) compressImageIfNeeded(imageURL string) (string, error)
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
img, format, err := image.Decode(bytes.NewReader(imgData))
|
// First decode config to check dimensions (prevents decompression bomb)
|
||||||
|
cfg, format, err := image.DecodeConfig(bytes.NewReader(imgData))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
// Limit decoded image to reasonable size (e.g., 4096x4096 = 64M pixels)
|
||||||
|
if int64(cfg.Width)*int64(cfg.Height) > 4096*4096 {
|
||||||
|
return "", fmt.Errorf("image too large: %dx%d", cfg.Width, cfg.Height)
|
||||||
|
}
|
||||||
|
// Full decode (already limited by size)
|
||||||
|
img, _, err := image.Decode(bytes.NewReader(imgData))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
_ = format // suppress unused warning
|
||||||
|
|
||||||
bounds := img.Bounds()
|
bounds := img.Bounds()
|
||||||
maxDim := uint(1024)
|
maxDim := uint(1024)
|
||||||
@ -332,7 +345,12 @@ func validateURL(rawURL string) error {
|
|||||||
// cleanupExpiredJobs 清理过期任务
|
// cleanupExpiredJobs 清理过期任务
|
||||||
func (s *minimaxService) cleanupExpiredJobs() {
|
func (s *minimaxService) cleanupExpiredJobs() {
|
||||||
ticker := time.NewTicker(1 * time.Hour)
|
ticker := time.NewTicker(1 * time.Hour)
|
||||||
for range ticker.C {
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-s.stopCh:
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
s.jobsLock.Lock()
|
s.jobsLock.Lock()
|
||||||
now := time.Now().UnixMilli()
|
now := time.Now().UnixMilli()
|
||||||
expiredThreshold := int64(24 * 60 * 60 * 1000) // 24h
|
expiredThreshold := int64(24 * 60 * 60 * 1000) // 24h
|
||||||
@ -346,3 +364,9 @@ func (s *minimaxService) cleanupExpiredJobs() {
|
|||||||
s.jobsLock.Unlock()
|
s.jobsLock.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close 关闭服务
|
||||||
|
func (s *minimaxService) Close() {
|
||||||
|
close(s.stopCh)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user