Skip to content

Commit

Permalink
Disallow operating on binary files in gist
Browse files Browse the repository at this point in the history
  • Loading branch information
g14a authored and mislav committed Mar 2, 2021
1 parent 50c49df commit 973fbb0
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 4 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/cli/safeexec v1.0.0
github.com/cpuguy83/go-md2man/v2 v2.0.0
github.com/enescakir/emoji v1.0.0
github.com/gabriel-vasile/mimetype v1.1.2
github.com/google/go-cmp v0.5.2
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/hashicorp/go-version v1.2.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ github.com/enescakir/emoji v1.0.0/go.mod h1:Bt1EKuLnKDTYpLALApstIkAjdDrS/8IAgTkK
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gabriel-vasile/mimetype v1.1.2 h1:gaPnPcNor5aZSVCJVSGipcpbgMWiAAj9z182ocSGbHU=
github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
Expand Down
15 changes: 13 additions & 2 deletions pkg/cmd/gist/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ type CreateOptions struct {
Public bool
Filenames []string
FilenameOverride string

WebMode bool
WebMode bool

HttpClient func() (*http.Client, error)
}
Expand Down Expand Up @@ -164,6 +163,8 @@ func processFiles(stdin io.ReadCloser, filenameOverride string, filenames []stri
var filename string
var content []byte
var err error
var isBinary bool

if f == "-" {
if filenameOverride != "" {
filename = filenameOverride
Expand All @@ -180,6 +181,16 @@ func processFiles(stdin io.ReadCloser, filenameOverride string, filenames []stri
if err != nil {
return fs, fmt.Errorf("failed to read file %s: %w", f, err)
}

isBinary, err = shared.IsBinaryContents(content)
if err != nil {
return nil, err
}

if isBinary {
return nil, fmt.Errorf("binary file not supported")
}

filename = path.Base(f)
}

Expand Down
9 changes: 9 additions & 0 deletions pkg/cmd/gist/edit/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ func editRun(opts *EditOptions) error {
return fmt.Errorf("gist has no file %q", filename)
}

isBinary, err := shared.IsBinaryContents([]byte(gist.Files[filename].Content))
if err != nil {
return err
}

if isBinary {
return fmt.Errorf("Editing binary files not supported")
}

editorCommand, err := cmdutil.DetermineEditor(opts.Config)
if err != nil {
return err
Expand Down
1 change: 0 additions & 1 deletion pkg/cmd/gist/edit/edit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ func Test_editRun(t *testing.T) {
io.SetStdoutTTY(!tt.nontty)
io.SetStdinTTY(!tt.nontty)
tt.opts.IO = io

tt.opts.Selector = "1234"

tt.opts.Config = func() (config.Config, error) {
Expand Down
32 changes: 32 additions & 0 deletions pkg/cmd/gist/shared/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/gabriel-vasile/mimetype"
"net/http"
"net/url"
"strings"
Expand Down Expand Up @@ -147,3 +148,34 @@ pagination:

return gists, nil
}

func IsBinaryFile(file string) (bool, error) {
detectedMime, err := mimetype.DetectFile(file)
if err != nil {
return false, err
}

isBinary := true

for mime := detectedMime; mime != nil; mime = mime.Parent() {
if mime.Is("text/plain") {
isBinary = false
}
}

return isBinary, nil
}

func IsBinaryContents(contents []byte) (bool, error) {
detectedMime := mimetype.Detect(contents)

isBinary := true

for mime := detectedMime; mime != nil; mime = mime.Parent() {
if mime.Is("text/plain") {
isBinary = false
}
}

return isBinary, nil
}
31 changes: 31 additions & 0 deletions pkg/cmd/gist/shared/shared_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,34 @@ func Test_GetGistIDFromURL(t *testing.T) {
})
}
}

func TestIsBinaryContents(t *testing.T) {
tests := []struct {
fileContent []byte
want bool
}{
{
want: false,
fileContent: []byte("package main"),
},
{
want: true,
fileContent: []byte{239, 191, 189, 239, 191, 189, 239, 191, 189, 239,
191, 189, 239, 191, 189, 16, 74, 70, 73, 70, 239, 191, 189, 1, 1, 1,
1, 44, 1, 44, 239, 191, 189, 239, 191, 189, 239, 191, 189, 239, 191,
189, 239, 191, 189, 67, 239, 191, 189, 8, 6, 6, 7, 6, 5, 8, 7, 7, 7,
9, 9, 8, 10, 12, 20, 10, 12, 11, 11, 12, 25, 18, 19, 15, 20, 29, 26,
31, 30, 29, 26, 28, 28, 32, 36, 46, 39, 32, 34, 44, 35, 28, 28, 40,
55, 41, 44, 48, 49, 52, 52, 52, 31, 39, 57, 61, 56, 50, 60, 46, 51,
52, 50, 239, 191, 189, 239, 191, 189, 239, 191, 189, 67, 1, 9, 9, 9, 12},
},
}

for _, tt := range tests {
isBinary, err := IsBinaryContents(tt.fileContent)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, tt.want, isBinary)
}
}
33 changes: 32 additions & 1 deletion pkg/cmd/gist/view/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ func viewRun(opts *ViewOptions) error {
defer opts.IO.StopPager()

render := func(gf *shared.GistFile) error {
isBinary, err := shared.IsBinaryContents([]byte(gf.Content))
if err != nil {
return err
}

if isBinary {
gf.Content = "Skipping rendering binary content..."
}

if strings.Contains(gf.Type, "markdown") && !opts.Raw {
rendered, err := markdown.Render(gf.Content, markdownStyle, "")
if err != nil {
Expand All @@ -134,6 +143,7 @@ func viewRun(opts *ViewOptions) error {
_, err := fmt.Fprint(opts.IO.Out, "\n")
return err
}

return nil
}

Expand All @@ -142,6 +152,16 @@ func viewRun(opts *ViewOptions) error {
if !ok {
return fmt.Errorf("gist has no such file: %q", opts.Filename)
}

isBinary, err := shared.IsBinaryContents([]byte(gistFile.Content))
if err != nil {
return err
}

if isBinary {
return fmt.Errorf("Error: file contents is binary")
}

return render(gistFile)
}

Expand All @@ -154,8 +174,19 @@ func viewRun(opts *ViewOptions) error {
for fn := range gist.Files {
filenames = append(filenames, fn)
}
sort.Strings(filenames)

if len(filenames) == 1 {
isBinary, err := shared.IsBinaryContents([]byte(gist.Files[filenames[0]].Content))
if err != nil {
return err
}

if isBinary {
return fmt.Errorf("Error: file contents is binary")
}
}

sort.Strings(filenames)
if opts.ListFiles {
for _, fn := range filenames {
fmt.Fprintln(opts.IO.Out, fn)
Expand Down

0 comments on commit 973fbb0

Please sign in to comment.