From bbd9b7e7d873394cb5c1587ecca70073a7641446 Mon Sep 17 00:00:00 2001 From: Anna Bogacheva Date: Sun, 17 Mar 2024 13:38:57 +0300 Subject: [PATCH 1/2] fix --- 03-fuzz/bogacheva/sstable-panesh-bogacheva.go | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 03-fuzz/bogacheva/sstable-panesh-bogacheva.go diff --git a/03-fuzz/bogacheva/sstable-panesh-bogacheva.go b/03-fuzz/bogacheva/sstable-panesh-bogacheva.go new file mode 100644 index 00000000..154738f0 --- /dev/null +++ b/03-fuzz/bogacheva/sstable-panesh-bogacheva.go @@ -0,0 +1,168 @@ +package main + +import ( + "bytes" + "encoding/binary" + "encoding/gob" + "errors" + "io" + "log" + "os" + "path" + "strconv" + "strings" + + "github.com/cockroachdb/pebble/sstable" + "github.com/cockroachdb/pebble/vfs" +) + +type Project struct { + Repo [59]byte + Mark uint8 +} + +type Student struct { + Name [32]byte + Login [16]byte + Group [8]byte + Practice [8]uint8 + Project + Mark float32 +} + +func readBinary(filename string) ([]Student, error) { + file, err := os.Open(filename) + if err != nil { + return nil, err + } + defer file.Close() + + var students []Student + for { + var st Student + err := binary.Read(file, binary.LittleEndian, &st) + if errors.Is(err, io.EOF) { + break + } + if err != nil { + return nil, err + } + students = append(students, st) + } + + return students, nil +} + +func writeBinary(students []Student, filename string) error { + file, err := os.Create(filename) + if err != nil { + return err + } + defer file.Close() + + for _, s := range students { + err := binary.Write(file, binary.LittleEndian, &s) + if err != nil { + return err + } + } + return nil +} + +func readSSTable(filename string) ([]Student, error) { + file, err := vfs.Default.Open(filename) + if err != nil { + return nil, err + } + readable, err := sstable.NewSimpleReadable(file) + if err != nil { + return nil, err + } + reader, err := sstable.NewReader(readable, sstable.ReaderOptions{}) + if err != nil { + return nil, err + } + i, err := reader.NewIter(nil, nil) + if err != nil { + return nil, err + } + students := []Student{} + for key, value := i.First(); key != nil; key, value = i.Next() { + dec := gob.NewDecoder(bytes.NewBuffer(value.InPlaceValue())) + var s Student + err := dec.Decode(&s) + if err != nil { + return nil, err + } + students = append(students, s) + } + if err := i.Close(); err != nil { + return nil, err + } + return students, nil +} + +func writeSSTable(students []Student, filename string) error { + file, err := os.Create(filename) + if err != nil { + return err + } + defer file.Close() + + w := sstable.NewWriter(file, sstable.WriterOptions{}) + for i, s := range students { + var sBuf bytes.Buffer + enc := gob.NewEncoder(&sBuf) + err = enc.Encode(s) + if err != nil { + return err + } + + err = w.Set([]byte(strconv.Itoa(i)), sBuf.Bytes()) + if err != nil { + return err + } + } + + return w.Close() +} + +func main() { + filename := os.Args[1] + ext := path.Ext(filename) + switch { + case ext == ".bin": + students, err := readBinary(filename) + if err != nil { + log.Fatalf("Failed to read file %s: %v\n", filename, err) + os.Exit(-1) + } + newFilename := strings.TrimSuffix(filename, ext) + ".sstable" + log.Println(filename, "->", newFilename) + if err = writeSSTable(students, newFilename); err != nil { + log.Fatalf("Failed to write file %s: %v\n", newFilename, err) + os.Exit(-1) + } + case ext == ".sstable": + students, err := readSSTable(filename) + if err != nil { + log.Fatalf("Failed to read file %s: %v\n", filename, err) + os.Exit(-1) + } + newFilename := strings.TrimSuffix(filename, ext) + ".bin" + log.Println(filename, "->", newFilename) + if err = writeBinary(students, newFilename); err != nil { + log.Fatalf("Failed to write file %s: %v\n", newFilename, err) + os.Exit(-1) + } + default: + log.Fatalf("Unsupported file extension: %s\n", ext) + os.Exit(-1) + } +} + +/*Удаление паники: В изначальном коде при возникновении ошибки вызывалась паника (panic(err)), что приводило к нежелательному завершению работы программы. В моем коде я заменила эти вызовы паники на возврат ошибок функциями чтения и записи, с последующим контролем этих ошибок в функции main. + +Устранение требования к формату файла: В изначальном коде не было проверки на соответствие формата файла, что могло привести к ошибкам при попытке прочитать файл, не удовлетворяющий ожидаемому формату. В моем коде я добавила проверки на ошибки после функций чтения, чтобы обеспечить правильное преждевременное завершение, если формат файла не поддерживается. + +Обратимость преобразования данных: Исходный код не гарантировал, что преобразование данных в обе стороны (из бинарного в SSTable и обратно) будет порождать идентичные данные. В моем коде, методы записи и чтения обеспечивают обратимость этого преобразования, за исключением того, что порядок студентов в исходном и конечном массиве может отличаться.*/ From b0b1cbc906fe7089433c2def8525dcc10cd021df Mon Sep 17 00:00:00 2001 From: Anna Bogacheva Date: Sun, 24 Mar 2024 21:35:31 +0900 Subject: [PATCH 2/2] fix --- 03-fuzz/bogacheva/fuzzer/main.go | 94 +++++++++++++++++++ ...heva.go => sstable-panesh-bogacheva.go.go} | 42 ++++----- 2 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 03-fuzz/bogacheva/fuzzer/main.go rename 03-fuzz/bogacheva/{sstable-panesh-bogacheva.go => sstable-panesh-bogacheva.go.go} (50%) diff --git a/03-fuzz/bogacheva/fuzzer/main.go b/03-fuzz/bogacheva/fuzzer/main.go new file mode 100644 index 00000000..fa493e5a --- /dev/null +++ b/03-fuzz/bogacheva/fuzzer/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "encoding/binary" + "fmt" + "log" + "math/rand" + "os" + "os/exec" +) + +type Project struct { + Repo [59]byte + Mark uint8 +} + +type Student struct { + Name [32]byte + Login [16]byte + Group [8]byte + Practice [8]uint8 + Project + Mark float32 +} + +func generateRandomBytes(n int) []byte { + b := make([]byte, n) + rand.Read(b) + return b +} + +func fuzzTest() { + log.Printf("Start fuzzing") + fileName := "test.bin" + file, err := os.Create(fileName) + if err != nil { + panic(err) + } + defer file.Close() + defer os.Remove(fileName) + + var students [1000]Student + for i := range students { + copy(students[i].Name[:], generateRandomBytes(32)) + copy(students[i].Login[:], generateRandomBytes(16)) + copy(students[i].Group[:], generateRandomBytes(8)) + for j := range students[i].Practice { + students[i].Practice[j] = uint8(rand.Intn(256)) + } + copy(students[i].Repo[:], generateRandomBytes(59)) + students[i].Mark = float32(rand.Float64()) + + err = binary.Write(file, binary.LittleEndian, &students[i]) + if err != nil { + panic(err) + } + } + + cmd := exec.Command("go", "run", "../sstable-panesh-bogacheva.go.go", fileName) + cmd.Stderr = os.Stderr + if err = cmd.Start(); err != nil { + log.Fatal("Failed to start fuzzer: ", err) + } + + err = cmd.Wait() + if exitError, ok := err.(*exec.ExitError); ok { + code := exitError.ExitCode() + if code != 1 { + fmt.Println("Fuzzing test failed: Binary expected to reject malformed input, but it did not.") + fmt.Println(code) + } else { + fmt.Println("Fuzzing test passed: Binary correctly rejected malformed input.") + } + return + } + + if err != nil { + log.Fatal("Fuzzer crashed: ", err) + } + + fmt.Println("Fuzzing test passed: Binary correctly handled malformed input.") +} + +func main() { + for i := 0; i < 10000000000; i++ { + fuzzTest() + } +} + +/*Удаление паники: В изначальном коде при возникновении ошибки вызывалась паника (panic(err)), что приводило к нежелательному завершению работы программы. В моем коде я заменила эти вызовы паники на возврат ошибок функциями чтения и записи, с последующим контролем этих ошибок в функции main. + +Устранение требования к формату файла: В изначальном коде не было проверки на соответствие формата файла, что могло привести к ошибкам при попытке прочитать файл, не удовлетворяющий ожидаемому формату. В моем коде я добавила проверки на ошибки после функций чтения, чтобы обеспечить правильное преждевременное завершение, если формат файла не поддерживается. + +Обратимость преобразования данных: Исходный код не гарантировал, что преобразование данных в обе стороны (из бинарного в SSTable и обратно) будет порождать идентичные данные. В моем коде, методы записи и чтения обеспечивают обратимость этого преобразования, за исключением того, что порядок студентов в исходном и конечном массиве может отличаться.*/ diff --git a/03-fuzz/bogacheva/sstable-panesh-bogacheva.go b/03-fuzz/bogacheva/sstable-panesh-bogacheva.go.go similarity index 50% rename from 03-fuzz/bogacheva/sstable-panesh-bogacheva.go rename to 03-fuzz/bogacheva/sstable-panesh-bogacheva.go.go index 154738f0..83e45420 100644 --- a/03-fuzz/bogacheva/sstable-panesh-bogacheva.go +++ b/03-fuzz/bogacheva/sstable-panesh-bogacheva.go.go @@ -70,25 +70,26 @@ func writeBinary(students []Student, filename string) error { } func readSSTable(filename string) ([]Student, error) { - file, err := vfs.Default.Open(filename) - if err != nil { - return nil, err - } - readable, err := sstable.NewSimpleReadable(file) + file, err := os.Open(filename) if err != nil { return nil, err } - reader, err := sstable.NewReader(readable, sstable.ReaderOptions{}) + + defer file.Close() + + reader, err := sstable.NewReader(file, sstable.ReaderOptions{}) if err != nil { return nil, err } + i, err := reader.NewIter(nil, nil) if err != nil { return nil, err } + students := []Student{} for key, value := i.First(); key != nil; key, value = i.Next() { - dec := gob.NewDecoder(bytes.NewBuffer(value.InPlaceValue())) + dec := gob.NewDecoder(bytes.NewBuffer(value)) var s Student err := dec.Decode(&s) if err != nil { @@ -96,6 +97,7 @@ func readSSTable(filename string) ([]Student, error) { } students = append(students, s) } + if err := i.Close(); err != nil { return nil, err } @@ -103,13 +105,13 @@ func readSSTable(filename string) ([]Student, error) { } func writeSSTable(students []Student, filename string) error { - file, err := os.Create(filename) + mem := vfs.NewMem() + f, err := mem.Create(filename) if err != nil { return err } - defer file.Close() - w := sstable.NewWriter(file, sstable.WriterOptions{}) + w := sstable.NewWriter(f, sstable.WriterOptions{}) for i, s := range students { var sBuf bytes.Buffer enc := gob.NewEncoder(&sBuf) @@ -128,41 +130,37 @@ func writeSSTable(students []Student, filename string) error { } func main() { - filename := os.Args[1] + args := os.Args + filename := args[1] ext := path.Ext(filename) switch { case ext == ".bin": students, err := readBinary(filename) if err != nil { - log.Fatalf("Failed to read file %s: %v\n", filename, err) + log.Printf("Failed to read file %s: %v\n", filename, err) os.Exit(-1) } newFilename := strings.TrimSuffix(filename, ext) + ".sstable" log.Println(filename, "->", newFilename) if err = writeSSTable(students, newFilename); err != nil { - log.Fatalf("Failed to write file %s: %v\n", newFilename, err) + log.Printf("Failed to write file %s: %v\n", newFilename, err) os.Exit(-1) + return } case ext == ".sstable": students, err := readSSTable(filename) if err != nil { - log.Fatalf("Failed to read file %s: %v\n", filename, err) + log.Printf("Failed to read file %s: %v\n", filename, err) os.Exit(-1) } newFilename := strings.TrimSuffix(filename, ext) + ".bin" log.Println(filename, "->", newFilename) if err = writeBinary(students, newFilename); err != nil { - log.Fatalf("Failed to write file %s: %v\n", newFilename, err) + log.Printf("Failed to write file %s: %v\n", newFilename, err) os.Exit(-1) } default: - log.Fatalf("Unsupported file extension: %s\n", ext) + log.Printf("Unsupported file extension: %s\n", ext) os.Exit(-1) } } - -/*Удаление паники: В изначальном коде при возникновении ошибки вызывалась паника (panic(err)), что приводило к нежелательному завершению работы программы. В моем коде я заменила эти вызовы паники на возврат ошибок функциями чтения и записи, с последующим контролем этих ошибок в функции main. - -Устранение требования к формату файла: В изначальном коде не было проверки на соответствие формата файла, что могло привести к ошибкам при попытке прочитать файл, не удовлетворяющий ожидаемому формату. В моем коде я добавила проверки на ошибки после функций чтения, чтобы обеспечить правильное преждевременное завершение, если формат файла не поддерживается. - -Обратимость преобразования данных: Исходный код не гарантировал, что преобразование данных в обе стороны (из бинарного в SSTable и обратно) будет порождать идентичные данные. В моем коде, методы записи и чтения обеспечивают обратимость этого преобразования, за исключением того, что порядок студентов в исходном и конечном массиве может отличаться.*/