shell OOM #93

Merged
sky22333 merged 1 commits from registry-alpha into main 2026-01-10 23:11:02 +08:00
2 changed files with 24 additions and 20 deletions

View File

@@ -171,9 +171,9 @@ func proxyGitHubWithRedirect(c *gin.Context, u string, redirectCount int) {
processedBody, processedSize, err := utils.ProcessSmart(resp.Body, isGzipCompressed, realHost)
if err != nil {
fmt.Printf("智能处理失败,回退到直接代理: %v\n", err)
processedBody = resp.Body
processedSize = 0
fmt.Printf("脚本处理失败: %v\n", err)
c.String(http.StatusBadGateway, "Script processing failed: %v", err)
return
}
// 智能设置响应头
coderabbitai[bot] commented 2026-01-10 23:07:44 +08:00 (Migrated from github.com)
Review

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n src/handlers/github.go | sed -n '160,190p'

Repository: sky22333/hubproxy

Length of output: 1228


🏁 Script executed:

# Find the ProcessSmart function definition
rg -n "ProcessSmart" src/

Repository: sky22333/hubproxy

Length of output: 365


🏁 Script executed:

# Check the file size first to see if we need to read selectively
wc -l src/handlers/github.go

Repository: sky22333/hubproxy

Length of output: 87


🏁 Script executed:

cat -n src/utils/proxy_shell.go

Repository: sky22333/hubproxy

Length of output: 3571


🏁 Script executed:

# Check if there's a git log showing the change
git log --oneline -20 src/handlers/github.go 2>/dev/null || echo "Git history not available"

Repository: sky22333/hubproxy

Length of output: 78


🏁 Script executed:

# Look for any fallback patterns or conditional error handling in github.go
cat -n src/handlers/github.go | sed -n '165,210p'

Repository: sky22333/hubproxy

Length of output: 1526


🏁 Script executed:

# Check if there's a fallback behavior in the else branch (for non-.sh/.ps1 files)
cat -n src/handlers/github.go | sed -n '209,232p'

Repository: sky22333/hubproxy

Length of output: 680


🏁 Script executed:

# Look for any recent changes or comments about previous behavior
git show HEAD src/handlers/github.go 2>/dev/null | head -100 || echo "Git show not available"

Repository: sky22333/hubproxy

Length of output: 3210


Consider differentiating error handling by error type.

The error handling treats all ProcessSmart errors uniformly (returning 502). Since different failures have different implications—size limit exceeded (the OOM prevention goal) versus transient decompression or read errors—consider whether transient errors warrant different treatment such as retry logic or fallback behavior, while size-limit errors appropriately trigger 502.

_⚠️ Potential issue_ | _🟡 Minor_ <details> <summary>🧩 Analysis chain</summary> 🏁 Script executed: ```shell cat -n src/handlers/github.go | sed -n '160,190p' ``` Repository: sky22333/hubproxy Length of output: 1228 --- 🏁 Script executed: ```shell # Find the ProcessSmart function definition rg -n "ProcessSmart" src/ ``` Repository: sky22333/hubproxy Length of output: 365 --- 🏁 Script executed: ```shell # Check the file size first to see if we need to read selectively wc -l src/handlers/github.go ``` Repository: sky22333/hubproxy Length of output: 87 --- 🏁 Script executed: ```shell cat -n src/utils/proxy_shell.go ``` Repository: sky22333/hubproxy Length of output: 3571 --- 🏁 Script executed: ```shell # Check if there's a git log showing the change git log --oneline -20 src/handlers/github.go 2>/dev/null || echo "Git history not available" ``` Repository: sky22333/hubproxy Length of output: 78 --- 🏁 Script executed: ```shell # Look for any fallback patterns or conditional error handling in github.go cat -n src/handlers/github.go | sed -n '165,210p' ``` Repository: sky22333/hubproxy Length of output: 1526 --- 🏁 Script executed: ```shell # Check if there's a fallback behavior in the else branch (for non-.sh/.ps1 files) cat -n src/handlers/github.go | sed -n '209,232p' ``` Repository: sky22333/hubproxy Length of output: 680 --- 🏁 Script executed: ```shell # Look for any recent changes or comments about previous behavior git show HEAD src/handlers/github.go 2>/dev/null | head -100 || echo "Git show not available" ``` Repository: sky22333/hubproxy Length of output: 3210 --- </details> **Consider differentiating error handling by error type.** The error handling treats all ProcessSmart errors uniformly (returning 502). Since different failures have different implications—size limit exceeded (the OOM prevention goal) versus transient decompression or read errors—consider whether transient errors warrant different treatment such as retry logic or fallback behavior, while size-limit errors appropriately trigger 502. <!-- fingerprinting:phantom:poseidon:puma --> <!-- This is an auto-generated comment by CodeRabbit -->

View File

@@ -12,47 +12,44 @@ import (
// GitHub URL正则表达式
var githubRegex = regexp.MustCompile(`(?:^|[\s'"(=,\[{;|&<>])https?://(?:github\.com|raw\.githubusercontent\.com|raw\.github\.com|gist\.githubusercontent\.com|gist\.github\.com|api\.github\.com)[^\s'")]*`)
// ProcessSmart Shell脚本智能处理函数
func ProcessSmart(input io.ReadCloser, isCompressed bool, host string) (io.Reader, int64, error) {
defer input.Close()
// MaxShellSize 限制最大处理大小为 10MB
const MaxShellSize = 10 * 1024 * 1024
// ProcessSmart Shell脚本智能处理函数
func ProcessSmart(input io.Reader, isCompressed bool, host string) (io.Reader, int64, error) {
content, err := readShellContent(input, isCompressed)
if err != nil {
return nil, 0, fmt.Errorf("内容读取失败: %v", err)
return nil, 0, err
}
if len(content) == 0 {
return strings.NewReader(""), 0, nil
}
if len(content) > 10*1024*1024 {
return strings.NewReader(content), int64(len(content)), nil
if !bytes.Contains(content, []byte("github.com")) && !bytes.Contains(content, []byte("githubusercontent.com")) {
return bytes.NewReader(content), int64(len(content)), nil
}
if !strings.Contains(content, "github.com") && !strings.Contains(content, "githubusercontent.com") {
return strings.NewReader(content), int64(len(content)), nil
}
processed := processGitHubURLs(content, host)
processed := processGitHubURLs(string(content), host)
return strings.NewReader(processed), int64(len(processed)), nil
}
func readShellContent(input io.ReadCloser, isCompressed bool) (string, error) {
func readShellContent(input io.Reader, isCompressed bool) ([]byte, error) {
var reader io.Reader = input
if isCompressed {
peek := make([]byte, 2)
n, err := input.Read(peek)
if err != nil && err != io.EOF {
return "", fmt.Errorf("读取数据失败: %v", err)
return nil, fmt.Errorf("读取数据失败: %v", err)
}
if n >= 2 && peek[0] == 0x1f && peek[1] == 0x8b {
combinedReader := io.MultiReader(bytes.NewReader(peek[:n]), input)
gzReader, err := gzip.NewReader(combinedReader)
if err != nil {
return "", fmt.Errorf("gzip解压失败: %v", err)
return nil, fmt.Errorf("gzip解压失败: %v", err)
}
defer gzReader.Close()
reader = gzReader
@@ -61,12 +58,19 @@ func readShellContent(input io.ReadCloser, isCompressed bool) (string, error) {
}
}
data, err := io.ReadAll(reader)
limit := int64(MaxShellSize + 1)
limitedReader := io.LimitReader(reader, limit)
data, err := io.ReadAll(limitedReader)
if err != nil {
return "", fmt.Errorf("读取内容失败: %v", err)
return nil, fmt.Errorf("读取内容失败: %v", err)
}
return string(data), nil
if int64(len(data)) > MaxShellSize {
return nil, fmt.Errorf("脚本文件过大,超过 %d MB 限制", MaxShellSize/1024/1024)
}
return data, nil
}
func processGitHubURLs(content, host string) string {