2020-06-19 13:31:20 +00:00
|
|
|
package logistic
|
|
|
|
|
|
|
|
import (
|
|
|
|
"archive/tar"
|
|
|
|
"bytes"
|
2020-06-19 23:06:47 +00:00
|
|
|
"compress/flate"
|
2020-06-19 13:31:20 +00:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
"os"
|
2021-04-22 19:46:01 +00:00
|
|
|
"strings"
|
2020-06-19 13:31:20 +00:00
|
|
|
)
|
|
|
|
|
2021-04-22 19:46:01 +00:00
|
|
|
// PackFuzzers packs all targeted fuzzers into a TAR - at least queue/, fuzz_bitmap, fuzzer_stats
|
|
|
|
func PackFuzzers(fuzzers []string, fuzzerDirectory string) ([]byte, error) {
|
|
|
|
// Create TAR archive
|
|
|
|
var tarBuffer bytes.Buffer
|
|
|
|
tarWriter := tar.NewWriter(&tarBuffer)
|
|
|
|
|
|
|
|
// Essentially we want to pack three things from each targeted fuzzer:
|
|
|
|
// - the fuzz_bitmap file
|
|
|
|
// - the fuzzer_stats file
|
|
|
|
// - the is_main_fuzzer file if present
|
|
|
|
// - the queue/ directory
|
|
|
|
for _, fuzzer := range fuzzers {
|
|
|
|
// We need full paths to read, but will write relative paths into the TAR archive
|
|
|
|
absFuzzerPath := fuzzerDirectory
|
|
|
|
relFuzzerPath := strings.TrimPrefix(fuzzer, fuzzerDirectory)
|
|
|
|
|
|
|
|
// Read-n-Pack™
|
|
|
|
packSingleFile(tarWriter, absFuzzerPath, relFuzzerPath, "fuzz_bitmap", false)
|
|
|
|
packSingleFile(tarWriter, absFuzzerPath, relFuzzerPath, "fuzzer_stats", false)
|
|
|
|
packSingleFile(tarWriter, absFuzzerPath, relFuzzerPath, "is_main_fuzzer", true)
|
|
|
|
packQueueFiles(tarWriter, absFuzzerPath, relFuzzerPath)
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 19:46:01 +00:00
|
|
|
// Close TAR archive
|
|
|
|
tarWriter.Close()
|
|
|
|
|
2020-06-19 23:06:47 +00:00
|
|
|
// Prepare FLATE compression
|
|
|
|
var flateBuffer bytes.Buffer
|
|
|
|
flateWrite, flateErr := flate.NewWriter(&flateBuffer, flate.BestCompression)
|
|
|
|
if flateErr != nil {
|
|
|
|
return nil, fmt.Errorf("unable to prepare flate compressor: %s", flateErr)
|
|
|
|
}
|
|
|
|
|
2021-04-22 19:46:01 +00:00
|
|
|
// Apply FLATE compression
|
|
|
|
flateWrite.Write(tarBuffer.Bytes())
|
2020-06-19 23:06:47 +00:00
|
|
|
flateWrite.Close()
|
|
|
|
|
2021-04-22 19:46:01 +00:00
|
|
|
// Return result: a DEFLATEd TAR archive
|
2020-06-19 23:06:47 +00:00
|
|
|
return flateBuffer.Bytes(), nil
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 19:46:01 +00:00
|
|
|
// packSingleFile packs a single file and writes it to the archive
|
|
|
|
// fuzzerDirectory is the base directory, e.g. /project/fuzzers/
|
|
|
|
// fuzzer is the name of the fuzzer itself, e.g. main-fuzzer-01
|
|
|
|
// filename is the name of the file you want to pack, e.g. fuzzer_stats
|
|
|
|
// ignoreNotFound is just used for files which may not be present in all fuzzer directories, like is_main_fuzzer
|
|
|
|
func packSingleFile(tarWriter *tar.Writer, absPath string, relPath string, fileName string, ignoreNotFound bool) {
|
|
|
|
// Read file
|
|
|
|
readPath := fmt.Sprintf("%s%c%s%c%s", absPath, os.PathSeparator, relPath, os.PathSeparator, fileName)
|
|
|
|
contents, readErr := ioutil.ReadFile(readPath)
|
2020-06-19 13:31:20 +00:00
|
|
|
if readErr != nil {
|
2021-04-22 19:46:01 +00:00
|
|
|
if !ignoreNotFound {
|
|
|
|
log.Printf("Failed to read file %s: %s", readPath, readErr)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create header for this file
|
|
|
|
header := &tar.Header{
|
|
|
|
Name: fmt.Sprintf("%s%c%s", relPath, os.PathSeparator, fileName),
|
|
|
|
Mode: 0600,
|
|
|
|
Size: int64(len(contents)),
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 19:46:01 +00:00
|
|
|
// Add header and contents to archive
|
|
|
|
tarWriter.WriteHeader(header)
|
|
|
|
tarWriter.Write(contents)
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Packs the files in the given directory into a tar archive
|
2021-04-22 19:46:01 +00:00
|
|
|
func packQueueFiles(tarWriter *tar.Writer, absPath string, relPath string) {
|
2020-06-19 13:31:20 +00:00
|
|
|
// Get list of queue files
|
2021-04-22 19:46:01 +00:00
|
|
|
queuePath := fmt.Sprintf("%s%c%s%cqueue", absPath, os.PathSeparator, relPath, os.PathSeparator)
|
2020-06-19 13:31:20 +00:00
|
|
|
filesInDir, readErr := ioutil.ReadDir(queuePath)
|
|
|
|
if readErr != nil {
|
2021-04-22 19:46:01 +00:00
|
|
|
log.Printf("Failed to list directory content of %s: %s", queuePath, readErr)
|
|
|
|
return
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Walk over each file and add it to our archive
|
|
|
|
for _, f := range filesInDir {
|
|
|
|
// Check if we hit a directory (e.g. '.state')
|
|
|
|
if f.IsDir() {
|
|
|
|
// Ignore directories altogether
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-04-22 19:46:01 +00:00
|
|
|
// Pack into the archive
|
|
|
|
packSingleFile(tarWriter, absPath, relPath, fmt.Sprintf("queue%c%s", os.PathSeparator, f.Name()), false)
|
2020-06-19 13:31:20 +00:00
|
|
|
}
|
|
|
|
}
|