X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/blobdiff_plain/8fc43f8e53a60144f49b92a0c28b0c939a69d1c9..14d7c1fea979212eb27fe5df19b73415d70a0183:/hotline/file_path.go?ds=inline diff --git a/hotline/file_path.go b/hotline/file_path.go index 46ef97c..620f54d 100644 --- a/hotline/file_path.go +++ b/hotline/file_path.go @@ -5,6 +5,7 @@ import ( "bytes" "encoding/binary" "errors" + "fmt" "io" "path/filepath" "strings" @@ -34,6 +35,9 @@ func fileItemScanner(data []byte, _ bool) (advance int, token []byte, err error) // Write implements the io.Writer interface for FilePathItem func (fpi *FilePathItem) Write(b []byte) (n int, err error) { + if len(b) < 3 { + return n, errors.New("buflen too small") + } fpi.Len = b[2] fpi.Name = b[fileItemMinLen : fpi.Len+fileItemMinLen] @@ -45,6 +49,7 @@ type FilePath struct { Items []FilePathItem } +// Write implements io.Writer interface for FilePath func (fp *FilePath) Write(b []byte) (n int, err error) { reader := bytes.NewReader(b) err = binary.Read(reader, binary.BigEndian, &fp.ItemCount) @@ -61,7 +66,13 @@ func (fp *FilePath) Write(b []byte) (n int, err error) { for i := 0; i < int(binary.BigEndian.Uint16(fp.ItemCount[:])); i++ { var fpi FilePathItem scanner.Scan() - if _, err := fpi.Write(scanner.Bytes()); err != nil { + + // Make a new []byte slice and copy the scanner bytes to it. This is critical to avoid a data race as the + // scanner re-uses the buffer for subsequent scans. + buf := make([]byte, len(scanner.Bytes())) + copy(buf, scanner.Bytes()) + + if _, err := fpi.Write(buf); err != nil { return n, err } fp.Items = append(fp.Items, fpi) @@ -109,6 +120,9 @@ func readPath(fileRoot string, filePath, fileName []byte) (fullPath string, err subPath, filepath.Join("/", string(fileName)), ) - + fullPath, err = txtDecoder.String(fullPath) + if err != nil { + return "", fmt.Errorf("invalid filepath encoding: %w", err) + } return fullPath, nil }