Disallow operating on binary files in gist

This commit is contained in:
Gowtham Munukutla 2021-02-24 18:39:25 +05:30 committed by Mislav Marohnić
parent 50c49df41a
commit 973fbb0925
8 changed files with 120 additions and 4 deletions

1
go.mod
View file

@ -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

2
go.sum
View file

@ -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=

View file

@ -30,8 +30,7 @@ type CreateOptions struct {
Public bool
Filenames []string
FilenameOverride string
WebMode bool
WebMode bool
HttpClient func() (*http.Client, error)
}
@ -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
@ -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)
}

View file

@ -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

View file

@ -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) {

View file

@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/gabriel-vasile/mimetype"
"net/http"
"net/url"
"strings"
@ -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
}

View file

@ -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)
}
}

View file

@ -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 {
@ -134,6 +143,7 @@ func viewRun(opts *ViewOptions) error {
_, err := fmt.Fprint(opts.IO.Out, "\n")
return err
}
return nil
}
@ -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)
}
@ -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)