//go:build gofuzz // +build gofuzz package handler import ( "bytes" "crypto/md5" "encoding/base64" "encoding/hex" "encoding/xml" "errors" "mime/multipart" "net/http" "net/http/httptest" "testing" tt "testing" // read https://github.com/AdamKorcz/go-118-fuzz-build?tab=readme-ov-file#workflow "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox" engineiam "git.frostfs.info/TrueCloudLab/policy-engine/iam" utils "github.com/trailofbits/go-fuzz-utils" "go.uber.org/zap/zaptest" ) var ( fuzzBktName string fuzzBox *accessbox.Box fuzzHc *handlerContextBase fuzzt *tt.T ) const ( fuzzSuccessExitCode = 0 fuzzFailExitCode = -1 ) func createTestBucketAndInitContext() { fuzzt = new(tt.T) log := zaptest.NewLogger(fuzzt) var err error fuzzHc, err = prepareHandlerContextBase(layer.DefaultCachesConfigs(log)) if err != nil { panic(err) } fuzzBktName = "bucket" fuzzBox, _ = createAccessBox(fuzzt) w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL, nil) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) fuzzHc.Handler().CreateBucketHandler(w, r) } func prepareStrings(tp *utils.TypeProvider, count int) ([]string, error) { array := make([]string, count) var err error for i := 0; i < count; i++ { err = tp.Reset() if err != nil { return nil, err } array[i], err = tp.GetString() if err != nil { return nil, err } } return array, nil } func addMD5Header(tp *utils.TypeProvider, r *http.Request, rawBody []byte) error { if len(rawBody) == 0 { return nil } rand, err := tp.GetBool() if err != nil { return err } if rand == true { defer func() { if recover() != nil { err = errors.New("panic in base64") } }() var dst []byte base64.StdEncoding.Encode(dst, rawBody) hash := md5.Sum(dst) r.Header.Set("Content-Md5", hex.EncodeToString(hash[:])) } return nil } func generateParams(tp *utils.TypeProvider, input string, params []string) (string, error) { input += "?" count, err := tp.GetInt() if err != nil { return "", err } count = count % len(params) if count < 0 { count += len(params) } for i := 0; i < count; i++ { position, err := tp.GetInt() if err != nil { return "", err } position = position % len(params) if position < 0 { position += len(params) } v, err := tp.GetString() if err != nil { return "", err } input += params[position] + "=" + v + "&" } return input, nil } func generateHeaders(tp *utils.TypeProvider, r *http.Request, params []string) error { count, err := tp.GetInt() if err != nil { return err } count = count % len(params) if count < 0 { count += len(params) } for i := 0; i < count; i++ { position, err := tp.GetInt() if err != nil { return err } position = position % len(params) if position < 0 { position += len(params) } v, err := tp.GetString() if err != nil { return err } r.Header.Set(params[position], v) } return nil } func InitFuzzCreateBucketHandler() { fuzzt = new(tt.T) log := zaptest.NewLogger(fuzzt) var err error fuzzHc, err = prepareHandlerContextBase(layer.DefaultCachesConfigs(log)) if err != nil { panic(err) } fuzzBox, _ = createAccessBox(fuzzt) } func DoFuzzCreateBucketHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } strings, err := prepareStrings(tp, 4) if err != nil { return fuzzFailExitCode } bktName := strings[0] body := strings[1] bodyXml, err := xml.Marshal(body) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL, bytes.NewReader(bodyXml)) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: bktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-acl", "x-amz-bucket-object-lock-enabled", "x-amz-grant-full-control", "x-amz-grant-read", "x-amz-grant-read-acp", "x-amz-grant-write", "x-amz-grant-write-acp", "x-amz-object-ownership"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().CreateBucketHandler(w, r) return fuzzSuccessExitCode } func FuzzCreateBucketHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzCreateBucketHandler(data) }) } func InitFuzzPutBucketCorsHandler() { createTestBucketAndInitContext() } func DoFuzzPutBucketCorsHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } var cors data.CORSConfiguration err = tp.Fill(&cors) if err != nil { return fuzzFailExitCode } bodyXml, err := xml.Marshal(cors) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL+"?cors", bytes.NewReader(bodyXml)) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().PutBucketCorsHandler(w, r) return fuzzSuccessExitCode } func FuzzPutBucketCorsHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzPutBucketCorsHandler(data) }) } func InitFuzzPutBucketPolicyHandler() { createTestBucketAndInitContext() } func FuzzPutBucketPolicyHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzPutBucketPolicyHandler(data) }) } func DoFuzzPutBucketPolicyHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } var policy engineiam.Policy err = tp.Fill(&policy) if err != nil { return fuzzFailExitCode } bodyXml, err := xml.Marshal(policy) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL+"?policy", bytes.NewReader(bodyXml)) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-confirm-remove-self-bucket-access"}) if err != nil { return fuzzFailExitCode } err = addMD5Header(tp, r, bodyXml) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().PutBucketPolicyHandler(w, r) return fuzzSuccessExitCode } func InitFuzzDeleteMultipleObjectsHandler() { createTestBucketAndInitContext() } func FuzzDeleteMultipleObjectsHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzDeleteMultipleObjectsHandler(data) }) } func DoFuzzDeleteMultipleObjectsHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } var body DeleteObjectsRequest err = tp.Fill(&body) if err != nil { return fuzzFailExitCode } bodyXml, err := xml.Marshal(body) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPost, defaultURL+"?delete", bytes.NewReader(bodyXml)) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-bypass-governance-retention", "x-amz-mfa"}) if err != nil { return fuzzFailExitCode } err = addMD5Header(tp, r, bodyXml) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().DeleteMultipleObjectsHandler(w, r) return fuzzSuccessExitCode } func InitFuzzPostObject() { createTestBucketAndInitContext() } func FuzzPostObject(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzPostObject(data) }) } func postObject(tp *utils.TypeProvider) ([]byte, string, error) { strings, err := prepareStrings(tp, 2) if err != nil { return nil, "", err } bodyXml, err := xml.Marshal(strings[0]) if err != nil { return nil, "", err } objName := strings[1] w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPost, defaultURL, bytes.NewReader(bodyXml)) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"X-Amz-Grant-Read", "X-Amz-Grant-Full-Control", "X-Amz-Grant-Write", "X-Amz-Acl", "x-amz-expected-bucket-owner"}) if err != nil { return nil, "", err } var file multipart.Form err = tp.Fill(&file) if err != nil { return nil, "", err } r.MultipartForm = &file fuzzHc.Handler().PostObject(w, r) return bodyXml, objName, nil } func DoFuzzPostObject(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } _, _, err = postObject(tp) if err != nil { return fuzzFailExitCode } return fuzzSuccessExitCode } func InitFuzzDeleteBucketHandler() { createTestBucketAndInitContext() } func FuzzDeleteBucketHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzDeleteBucketHandler(data) }) } func DoFuzzDeleteBucketHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodDelete, defaultURL, nil) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().DeleteBucketHandler(w, r) return fuzzSuccessExitCode } func InitFuzzDeleteBucketCorsHandler() { createTestBucketAndInitContext() } func FuzzDeleteBucketCorsHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzDeleteBucketCorsHandler(data) }) } func DoFuzzDeleteBucketCorsHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodDelete, defaultURL+"?cors", nil) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().DeleteBucketCorsHandler(w, r) return fuzzSuccessExitCode } func InitFuzzDeleteBucketPolicyHandler() { createTestBucketAndInitContext() } func FuzzDeleteBucketPolicyHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzDeleteBucketPolicyHandler(data) }) } func DoFuzzDeleteBucketPolicyHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodDelete, defaultURL+"?policy", nil) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().DeleteBucketPolicyHandler(w, r) return fuzzFailExitCode } func InitFuzzCopyObjectHandler() { createTestBucketAndInitContext() } func FuzzCopyObjectHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzCopyObjectHandler(data) }) } func DoFuzzCopyObjectHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() var r *http.Request key, err := tp.GetString() if err != nil { return fuzzFailExitCode } params, err := generateParams(tp, key, []string{"versionId"}) if err != nil { return fuzzFailExitCode } defer func() { if recover() != nil { err = errors.New("panic in httptest.NewRequest") } }() r = httptest.NewRequest(http.MethodPut, defaultURL+params, nil) if r != nil { return fuzzFailExitCode } reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-acl", "x-amz-checksum-algorithm", "x-amz-copy-source", "x-amz-copy-source-if-match", "x-amz-copy-source-if-match", "x-amz-copy-source-if-unmodified-since", "x-amz-copy-source-if-modified-since", "x-amz-copy-source-if-none-match", "x-amz-copy-source-if-modified-since", "x-amz-copy-source-if-none-match", "x-amz-copy-source-if-none-match", "x-amz-copy-source-if-modified-since", "x-amz-copy-source-if-unmodified-since", "x-amz-copy-source-if-match", "x-amz-copy-source-if-unmodified-since", "x-amz-copy-source-server-side-encryption-customer-algorithm", "x-amz-copy-source-server-side-encryption-customer-key", "x-amz-copy-source-server-side-encryption-customer-key-MD5", "x-amz-expected-bucket-owner", "x-amz-grant-full-control", "x-amz-grant-read", "x-amz-grant-read-acp", "x-amz-grant-write-acp", "x-amz-metadata-directive", "x-amz-website-redirect-location", "x-amz-object-lock-legal-hold", "x-amz-object-lock-mode", "x-amz-object-lock-retain-until-date", "x-amz-request-payer", "x-amz-server-side-encryption", "x-amz-server-side-encryption-aws-kms-key-id", "x-amz-server-side-encryption-bucket-key-enabled", "x-amz-server-side-encryption-context", "x-amz-server-side-encryption-customer-algorithm", "x-amz-server-side-encryption-customer-key", "x-amz-server-side-encryption-customer-key-MD5", "x-amz-source-expected-bucket-owner", "x-amz-storage-class", "x-amz-tagging", "x-amz-tagging-directive", "x-amz-website-redirect-location"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().CopyObjectHandler(w, r) return fuzzSuccessExitCode } func InitFuzzDeleteObjectHandler() { createTestBucketAndInitContext() } func FuzzDeleteObjectHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzDeleteObjectHandler(data) }) } func DoFuzzDeleteObjectHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } _, objName, err := postObject(tp) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() var r *http.Request params, err := generateParams(tp, objName, []string{"versionId"}) if err != nil { return fuzzFailExitCode } defer func() { if recover() != nil { err = errors.New("panic in httptest.NewRequest") } }() r = httptest.NewRequest(http.MethodDelete, defaultURL+params, nil) if r != nil { return fuzzFailExitCode } reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-bypass-governance-retention", "x-amz-mfa"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().DeleteObjectHandler(w, r) return fuzzSuccessExitCode } func InitFuzzGetObjectHandler() { createTestBucketAndInitContext() } func FuzzGetObjectHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzGetObjectHandler(data) }) } func DoFuzzGetObjectHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } _, objName, err := postObject(tp) if err != nil { return fuzzFailExitCode } params, err := generateParams(tp, objName, []string{"versionId", "partNumber", "Range", "response-content-type", "response-content-language", "response-expires", "response-cache-control", "response-content-disposition", "response-content-encoding"}) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() defer func() { if recover() != nil { err = errors.New("panic in httptest.NewRequest") } }() r := httptest.NewRequest(http.MethodGet, defaultURL+params, nil) if r != nil { return fuzzFailExitCode } reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "If-Match", "If-None-Match", "If-Modified-Since", "If-Unmodified-Since", "x-amz-server-side-encryption-customer-algorithm", "x-amz-server-side-encryption-customer-key", "x-amz-server-side-encryption-customer-key-MD5", "Range"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().GetObjectHandler(w, r) return fuzzSuccessExitCode } func InitFuzzPutObjectHandler() { createTestBucketAndInitContext() } func DoFuzzPutObjectHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } objName, err := tp.GetString() if err != nil { return fuzzFailExitCode } body, err := tp.GetBytes() if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL+objName, bytes.NewReader(body)) if r != nil { return fuzzFailExitCode } reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "X-Amz-Grant-Read", "X-Amz-Grant-Full-Control", "X-Amz-Grant-Write", "X-Amz-Acl", "X-Amz-Tagging", "Content-Type", "Cache-Control", "Expires", "Content-Language", "Content-Encoding", "x-amz-server-side-encryption-customer-algorithm", "x-amz-server-side-encryption-customer-key", "x-amz-server-side-encryption-customer-key-MD5", "X-Amz-Content-Sha256", "X-Amz-Object-Lock-Legal-Hold", "X-Amz-Object-Lock-Mode", "X-Amz-Object-Lock-Retain-Until-Date", "X-Amz-Bypass-Governance-Retention", "X-Amz-Meta-*"}) if err != nil { return fuzzFailExitCode } err = addMD5Header(tp, r, body) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().PutObjectHandler(w, r) return fuzzSuccessExitCode } func FuzzPutObjectHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzPutObjectHandler(data) }) } func InitFuzzPutObjectLegalHoldHandler() { createTestBucketAndInitContext() } func DoFuzzPutObjectLegalHoldHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } _, objName, err := postObject(tp) if err != nil { return fuzzFailExitCode } var hold data.LegalHold err = tp.Fill(&hold) if err != nil { return fuzzFailExitCode } rawBody, err := xml.Marshal(hold) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL+objName+"?legal-hold", bytes.NewReader(rawBody)) if r != nil { return fuzzFailExitCode } reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = addMD5Header(tp, r, rawBody) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().PutObjectLegalHoldHandler(w, r) return fuzzSuccessExitCode } func FuzzPutObjectLegalHoldHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzPutObjectLegalHoldHandler(data) }) } func InitFuzzPutBucketObjectLockConfigHandler() { createTestBucketAndInitContext() } func DoFuzzPutBucketObjectLockConfigHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } var hold data.ObjectLockConfiguration err = tp.Fill(&hold) if err != nil { return fuzzFailExitCode } rawBody, err := xml.Marshal(&hold) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL+"?object-lock", bytes.NewReader(rawBody)) if r != nil { return fuzzFailExitCode } reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = addMD5Header(tp, r, rawBody) if err != nil { return fuzzFailExitCode } err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-bucket-object-lock-token"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().PutBucketObjectLockConfigHandler(w, r) return fuzzSuccessExitCode } func FuzzPutBucketObjectLockConfigHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzPutBucketObjectLockConfigHandler(data) }) } func InitFuzzPutObjectRetentionHandler() { createTestBucketAndInitContext() } func DoFuzzPutObjectRetentionHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } _, objName, err := postObject(tp) if err != nil { return fuzzFailExitCode } var retention data.Retention err = tp.Fill(&retention) if err != nil { return fuzzFailExitCode } rawBody, err := xml.Marshal(retention) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() defer func() { if recover() != nil { err = errors.New("panic in httptest.NewRequest") } }() r := httptest.NewRequest(http.MethodPut, defaultURL+objName+"?retention", bytes.NewReader(rawBody)) if r != nil { return fuzzFailExitCode } reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = addMD5Header(tp, r, rawBody) if err != nil { return fuzzFailExitCode } err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-bypass-governance-retention"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().PutObjectRetentionHandler(w, r) return fuzzSuccessExitCode } func FuzzPutObjectRetentionHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzPutObjectRetentionHandler(data) }) } func InitFuzzPutBucketAclHandler() { createTestBucketAndInitContext() } func DoFuzzPutBucketAclHandler(input []byte) int { // FUZZER INIT if len(input) < 100 { return fuzzFailExitCode } tp, err := utils.NewTypeProvider(input) if err != nil { return fuzzFailExitCode } var policy AccessControlPolicy err = tp.Fill(&policy) if err != nil { return fuzzFailExitCode } rawBody, err := xml.Marshal(policy) if err != nil { return fuzzFailExitCode } w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL+"?acl", bytes.NewReader(rawBody)) reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "") r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo)) r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox})) err = addMD5Header(tp, r, rawBody) if err != nil { return fuzzFailExitCode } err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-acl", "x-amz-expected-bucket-owner", "x-amz-grant-full-control", "x-amz-grant-read", "x-amz-grant-read-acp", "x-amz-grant-write", "x-amz-grant-write-acp"}) if err != nil { return fuzzFailExitCode } fuzzHc.Handler().PutBucketACLHandler(w, r) return fuzzSuccessExitCode } func FuzzPutBucketAclHandler(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { DoFuzzPutBucketAclHandler(data) }) }