// Package upload 测试头像上传的格式、尺寸与路径安全边界。 // 版本:v1.0.0 package upload import ( "bytes" "image" "image/color" "image/png" "path/filepath" "strings" "testing" ) // pngBytes 生成指定尺寸的有效 PNG 测试图片。 func pngBytes(t *testing.T, width, height int) []byte { t.Helper() picture := image.NewRGBA(image.Rect(0, 0, width, height)) picture.Set(0, 0, color.RGBA{R: 32, G: 96, B: 192, A: 255}) var buffer bytes.Buffer if err := png.Encode(&buffer, picture); err != nil { t.Fatalf("encode PNG: %v", err) } return buffer.Bytes() } // TestValidateAvatarAcceptsRealPNG 验证真实 PNG 可通过并规范化类型。 func TestValidateAvatarAcceptsRealPNG(t *testing.T) { extension, contentType, err := validateAvatar("头像.PNG", pngBytes(t, 2, 2)) if err != nil { t.Fatalf("valid PNG was rejected: %v", err) } if extension != ".png" || contentType != "image/png" { t.Fatalf("avatar metadata = (%q, %q)", extension, contentType) } } // TestValidateAvatarRejectsSpoofedAndOversizedImage 验证伪造扩展名与超大像素尺寸会被拒绝。 func TestValidateAvatarRejectsSpoofedAndOversizedImage(t *testing.T) { if _, _, err := validateAvatar("fake.png", []byte("not an image")); err == nil { t.Fatal("spoofed PNG was accepted") } if _, _, err := validateAvatar("wide.png", pngBytes(t, maxAvatarDimension+1, 1)); err == nil { t.Fatal("oversized image dimensions were accepted") } } // TestAvatarPathFromURIStaysInsideControlledRoot 验证头像 URI 不能逃逸受控目录。 func TestAvatarPathFromURIStaysInsideControlledRoot(t *testing.T) { root := t.TempDir() t.Setenv("HEQI_UPLOAD_DIR", root) path, err := avatarPathFromURI("/uploads/avatars/2026/08/10/example.png") if err != nil { t.Fatalf("controlled URI was rejected: %v", err) } expectedRoot := filepath.Join(root, "avatars") relative, err := filepath.Rel(expectedRoot, path) if err != nil || relative == ".." || strings.HasPrefix(relative, ".."+string(filepath.Separator)) { t.Fatalf("avatar path escaped root: %q", path) } for _, uri := range []string{ "https://example.com/avatar.png", "/uploads/example.png", "/uploads/avatars/../../secret.png", } { if _, err := avatarPathFromURI(uri); err == nil { t.Fatalf("unsafe avatar URI was accepted: %q", uri) } } }