X Tutup
Skip to content

Commit 973fbb0

Browse files
g14amislav
authored andcommitted
Disallow operating on binary files in gist
1 parent 50c49df commit 973fbb0

File tree

8 files changed

+120
-4
lines changed

8 files changed

+120
-4
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/cli/safeexec v1.0.0
1212
github.com/cpuguy83/go-md2man/v2 v2.0.0
1313
github.com/enescakir/emoji v1.0.0
14+
github.com/gabriel-vasile/mimetype v1.1.2
1415
github.com/google/go-cmp v0.5.2
1516
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
1617
github.com/hashicorp/go-version v1.2.1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ github.com/enescakir/emoji v1.0.0/go.mod h1:Bt1EKuLnKDTYpLALApstIkAjdDrS/8IAgTkK
7474
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
7575
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
7676
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
77+
github.com/gabriel-vasile/mimetype v1.1.2 h1:gaPnPcNor5aZSVCJVSGipcpbgMWiAAj9z182ocSGbHU=
78+
github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
7779
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
7880
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
7981
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=

pkg/cmd/gist/create/create.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ type CreateOptions struct {
3030
Public bool
3131
Filenames []string
3232
FilenameOverride string
33-
34-
WebMode bool
33+
WebMode bool
3534

3635
HttpClient func() (*http.Client, error)
3736
}
@@ -164,6 +163,8 @@ func processFiles(stdin io.ReadCloser, filenameOverride string, filenames []stri
164163
var filename string
165164
var content []byte
166165
var err error
166+
var isBinary bool
167+
167168
if f == "-" {
168169
if filenameOverride != "" {
169170
filename = filenameOverride
@@ -180,6 +181,16 @@ func processFiles(stdin io.ReadCloser, filenameOverride string, filenames []stri
180181
if err != nil {
181182
return fs, fmt.Errorf("failed to read file %s: %w", f, err)
182183
}
184+
185+
isBinary, err = shared.IsBinaryContents(content)
186+
if err != nil {
187+
return nil, err
188+
}
189+
190+
if isBinary {
191+
return nil, fmt.Errorf("binary file not supported")
192+
}
193+
183194
filename = path.Base(f)
184195
}
185196

pkg/cmd/gist/edit/edit.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ func editRun(opts *EditOptions) error {
148148
return fmt.Errorf("gist has no file %q", filename)
149149
}
150150

151+
isBinary, err := shared.IsBinaryContents([]byte(gist.Files[filename].Content))
152+
if err != nil {
153+
return err
154+
}
155+
156+
if isBinary {
157+
return fmt.Errorf("Editing binary files not supported")
158+
}
159+
151160
editorCommand, err := cmdutil.DetermineEditor(opts.Config)
152161
if err != nil {
153162
return err

pkg/cmd/gist/edit/edit_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,6 @@ func Test_editRun(t *testing.T) {
301301
io.SetStdoutTTY(!tt.nontty)
302302
io.SetStdinTTY(!tt.nontty)
303303
tt.opts.IO = io
304-
305304
tt.opts.Selector = "1234"
306305

307306
tt.opts.Config = func() (config.Config, error) {

pkg/cmd/gist/shared/shared.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"github.com/gabriel-vasile/mimetype"
78
"net/http"
89
"net/url"
910
"strings"
@@ -147,3 +148,34 @@ pagination:
147148

148149
return gists, nil
149150
}
151+
152+
func IsBinaryFile(file string) (bool, error) {
153+
detectedMime, err := mimetype.DetectFile(file)
154+
if err != nil {
155+
return false, err
156+
}
157+
158+
isBinary := true
159+
160+
for mime := detectedMime; mime != nil; mime = mime.Parent() {
161+
if mime.Is("text/plain") {
162+
isBinary = false
163+
}
164+
}
165+
166+
return isBinary, nil
167+
}
168+
169+
func IsBinaryContents(contents []byte) (bool, error) {
170+
detectedMime := mimetype.Detect(contents)
171+
172+
isBinary := true
173+
174+
for mime := detectedMime; mime != nil; mime = mime.Parent() {
175+
if mime.Is("text/plain") {
176+
isBinary = false
177+
}
178+
}
179+
180+
return isBinary, nil
181+
}

pkg/cmd/gist/shared/shared_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,34 @@ func Test_GetGistIDFromURL(t *testing.T) {
5050
})
5151
}
5252
}
53+
54+
func TestIsBinaryContents(t *testing.T) {
55+
tests := []struct {
56+
fileContent []byte
57+
want bool
58+
}{
59+
{
60+
want: false,
61+
fileContent: []byte("package main"),
62+
},
63+
{
64+
want: true,
65+
fileContent: []byte{239, 191, 189, 239, 191, 189, 239, 191, 189, 239,
66+
191, 189, 239, 191, 189, 16, 74, 70, 73, 70, 239, 191, 189, 1, 1, 1,
67+
1, 44, 1, 44, 239, 191, 189, 239, 191, 189, 239, 191, 189, 239, 191,
68+
189, 239, 191, 189, 67, 239, 191, 189, 8, 6, 6, 7, 6, 5, 8, 7, 7, 7,
69+
9, 9, 8, 10, 12, 20, 10, 12, 11, 11, 12, 25, 18, 19, 15, 20, 29, 26,
70+
31, 30, 29, 26, 28, 28, 32, 36, 46, 39, 32, 34, 44, 35, 28, 28, 40,
71+
55, 41, 44, 48, 49, 52, 52, 52, 31, 39, 57, 61, 56, 50, 60, 46, 51,
72+
52, 50, 239, 191, 189, 239, 191, 189, 239, 191, 189, 67, 1, 9, 9, 9, 12},
73+
},
74+
}
75+
76+
for _, tt := range tests {
77+
isBinary, err := IsBinaryContents(tt.fileContent)
78+
if err != nil {
79+
t.Fatal(err)
80+
}
81+
assert.Equal(t, tt.want, isBinary)
82+
}
83+
}

pkg/cmd/gist/view/view.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ func viewRun(opts *ViewOptions) error {
118118
defer opts.IO.StopPager()
119119

120120
render := func(gf *shared.GistFile) error {
121+
isBinary, err := shared.IsBinaryContents([]byte(gf.Content))
122+
if err != nil {
123+
return err
124+
}
125+
126+
if isBinary {
127+
gf.Content = "Skipping rendering binary content..."
128+
}
129+
121130
if strings.Contains(gf.Type, "markdown") && !opts.Raw {
122131
rendered, err := markdown.Render(gf.Content, markdownStyle, "")
123132
if err != nil {
@@ -134,6 +143,7 @@ func viewRun(opts *ViewOptions) error {
134143
_, err := fmt.Fprint(opts.IO.Out, "\n")
135144
return err
136145
}
146+
137147
return nil
138148
}
139149

@@ -142,6 +152,16 @@ func viewRun(opts *ViewOptions) error {
142152
if !ok {
143153
return fmt.Errorf("gist has no such file: %q", opts.Filename)
144154
}
155+
156+
isBinary, err := shared.IsBinaryContents([]byte(gistFile.Content))
157+
if err != nil {
158+
return err
159+
}
160+
161+
if isBinary {
162+
return fmt.Errorf("Error: file contents is binary")
163+
}
164+
145165
return render(gistFile)
146166
}
147167

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

178+
if len(filenames) == 1 {
179+
isBinary, err := shared.IsBinaryContents([]byte(gist.Files[filenames[0]].Content))
180+
if err != nil {
181+
return err
182+
}
183+
184+
if isBinary {
185+
return fmt.Errorf("Error: file contents is binary")
186+
}
187+
}
188+
189+
sort.Strings(filenames)
159190
if opts.ListFiles {
160191
for _, fn := range filenames {
161192
fmt.Fprintln(opts.IO.Out, fn)

0 commit comments

Comments
 (0)
X Tutup