Skip to content

Commit 502ae44

Browse files
authored
Merge pull request #57 from projectdiscovery/issue-53-memory-leak-on-large-file-download
Fixing memory leak on large file dump via max-dump-body-size
2 parents 5245952 + 99ee932 commit 502ae44

File tree

6 files changed

+54
-33
lines changed

6 files changed

+54
-33
lines changed

internal/runner/options.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,26 @@ import (
1212

1313
// Options of the tool
1414
type Options struct {
15-
ListenAddress string
16-
Folder string
17-
BasicAuth string
18-
username string
19-
password string
20-
Realm string
21-
TLSCertificate string
22-
TLSKey string
23-
TLSDomain string
24-
HTTPS bool
25-
Verbose bool
26-
EnableUpload bool
27-
EnableTCP bool
28-
RulesFile string
29-
TCPWithTLS bool
30-
Version bool
31-
Silent bool
32-
Sandbox bool
33-
MaxFileSize int
15+
ListenAddress string
16+
Folder string
17+
BasicAuth string
18+
username string
19+
password string
20+
Realm string
21+
TLSCertificate string
22+
TLSKey string
23+
TLSDomain string
24+
HTTPS bool
25+
Verbose bool
26+
EnableUpload bool
27+
EnableTCP bool
28+
RulesFile string
29+
TCPWithTLS bool
30+
Version bool
31+
Silent bool
32+
Sandbox bool
33+
MaxFileSize int
34+
MaxDumpBodySize int
3435
}
3536

3637
// ParseOptions parses the command line options for application
@@ -57,6 +58,7 @@ func ParseOptions() *Options {
5758
flag.BoolVar(&options.Silent, "silent", false, "Show only results in the output")
5859
flag.BoolVar(&options.Sandbox, "sandbox", false, "Enable sandbox mode")
5960
flag.IntVar(&options.MaxFileSize, "max-file-size", 50, "Max Upload File Size")
61+
flag.IntVar(&options.MaxDumpBodySize, "max-dump-body-size", -1, "Max Dump Body Size")
6062

6163
flag.Parse()
6264

internal/runner/runner.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"github.com/projectdiscovery/simplehttpserver/pkg/binder"
66
"github.com/projectdiscovery/simplehttpserver/pkg/httpserver"
77
"github.com/projectdiscovery/simplehttpserver/pkg/tcpserver"
8+
"github.com/projectdiscovery/simplehttpserver/pkg/unit"
89
)
910

1011
// Runner is a client for running the enumeration process.
@@ -59,6 +60,7 @@ func New(options *Options) (*Runner, error) {
5960
Verbose: r.options.Verbose,
6061
Sandbox: r.options.Sandbox,
6162
MaxFileSize: r.options.MaxFileSize,
63+
MaxDumpBodySize: unit.ToMb(r.options.MaxDumpBodySize),
6264
})
6365
if err != nil {
6466
return nil, err

pkg/httpserver/httpserver.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type Options struct {
2424
Verbose bool
2525
Sandbox bool
2626
MaxFileSize int // 50Mb
27+
MaxDumpBodySize int64
2728
}
2829

2930
// HTTPServer instance

pkg/httpserver/loglayer.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"path/filepath"
1010

1111
"github.com/projectdiscovery/gologger"
12+
"github.com/projectdiscovery/simplehttpserver/pkg/unit"
1213
)
1314

1415
// Convenience globals
@@ -17,10 +18,19 @@ var (
1718
EnableVerbose bool
1819
)
1920

21+
func (t *HTTPServer) shouldDumpBody(bodysize int64) bool {
22+
return t.options.MaxDumpBodySize > 0 && bodysize > t.options.MaxDumpBodySize
23+
}
24+
2025
func (t *HTTPServer) loglayer(handler http.Handler) http.Handler {
2126
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
22-
fullRequest, _ := httputil.DumpRequest(r, true)
23-
lrw := newLoggingResponseWriter(w)
27+
var fullRequest []byte
28+
if t.shouldDumpBody(r.ContentLength) {
29+
fullRequest, _ = httputil.DumpRequest(r, false)
30+
} else {
31+
fullRequest, _ = httputil.DumpRequest(r, true)
32+
}
33+
lrw := newLoggingResponseWriter(w, t.options.MaxDumpBodySize)
2434
handler.ServeHTTP(lrw, r)
2535

2636
// Handles file write if enabled
@@ -52,7 +62,7 @@ func (t *HTTPServer) loglayer(handler http.Handler) http.Handler {
5262
err error
5363
)
5464
if t.options.Sandbox {
55-
maxFileSize := toMb(t.options.MaxFileSize)
65+
maxFileSize := unit.ToMb(t.options.MaxFileSize)
5666
// check header content length
5767
if r.ContentLength > maxFileSize {
5868
gologger.Print().Msg("request too large")
@@ -81,24 +91,29 @@ func (t *HTTPServer) loglayer(handler http.Handler) http.Handler {
8191
lrw.Header().Write(headers) //nolint
8292
gologger.Print().Msgf("\nRemote Address: %s\n%s\n%s %d %s\n%s\n%s\n", r.RemoteAddr, string(fullRequest), r.Proto, lrw.statusCode, http.StatusText(lrw.statusCode), headers.String(), string(lrw.Data))
8393
} else {
84-
gologger.Print().Msgf("%s \"%s %s %s\" %d %d", r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, len(lrw.Data))
94+
gologger.Print().Msgf("%s \"%s %s %s\" %d %d", r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, lrw.Size)
8595
}
8696
})
8797
}
8898

8999
type loggingResponseWriter struct {
90100
http.ResponseWriter
91-
statusCode int
92-
Data []byte
101+
statusCode int
102+
Data []byte
103+
Size int
104+
MaxDumpSize int64
93105
}
94106

95-
func newLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter {
96-
return &loggingResponseWriter{w, http.StatusOK, []byte{}}
107+
func newLoggingResponseWriter(w http.ResponseWriter, maxSize int64) *loggingResponseWriter {
108+
return &loggingResponseWriter{w, http.StatusOK, []byte{}, 0, maxSize}
97109
}
98110

99111
// Write the data
100112
func (lrw *loggingResponseWriter) Write(data []byte) (int, error) {
101-
lrw.Data = append(lrw.Data, data...)
113+
if len(lrw.Data) < int(lrw.MaxDumpSize) {
114+
lrw.Data = append(lrw.Data, data...)
115+
}
116+
lrw.Size += len(data)
102117
return lrw.ResponseWriter.Write(data)
103118
}
104119

pkg/httpserver/util.go

Lines changed: 0 additions & 5 deletions
This file was deleted.

pkg/unit/unit.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package unit
2+
3+
// ToMb converts bytes to megabytes
4+
func ToMb(n int) int64 {
5+
return int64(n) * 1024 * 1024
6+
}

0 commit comments

Comments
 (0)