Skip to content

Commit a326f39

Browse files
dwisiswant0Ice3man543knakul853
authored
fix(tmplexec): memory blowup in multiproto (#6258)
* bugfix: fix memory blowup using previousEvent for multi-proto execution * refactor(tmplexec): uses supported protocol types Signed-off-by: Dwi Siswanto <[email protected]> * add co-author Co-authored-by: Nakul Bharti <[email protected]> Signed-off-by: Dwi Siswanto <[email protected]> * refactor(tmplexec): mv builder inside loop scope Signed-off-by: Dwi Siswanto <[email protected]> * refactor(tmplexec): skip existing keys in `FillPreviousEvent` The `FillPreviousEvent` func was modified to prevent overwriting/duplicating entries in the previous map. It now checks if a key `k` from `event.InternalEvent` already exists in the previous map. If it does, the key is skipped. This ensures that if `k` was already set (potentially w/o a prefix), it's not re-added with an `ID_` prefix. Additionally, keys in `event.InternalEvent` that already start with the current `ID_` prefix are also skipped to avoid redundant prefixing. This change simplifies the logic by removing the `reqTypeWithIndexRegex` and directly addresses the potential for duplicate / incorrectly prefixed keys when `event.InternalEvent` grows during protocol request execution. Signed-off-by: Dwi Siswanto <[email protected]> * chore(tmplexec): naming convention, `ID` => `protoID` Signed-off-by: Dwi Siswanto <[email protected]> * chore(tmplexec): it's request ID lol sorry Signed-off-by: Dwi Siswanto <[email protected]> --------- Signed-off-by: Dwi Siswanto <[email protected]> Co-authored-by: Ice3man <[email protected]> Co-authored-by: Nakul Bharti <[email protected]>
1 parent 797ceb5 commit a326f39

File tree

3 files changed

+40
-24
lines changed

3 files changed

+40
-24
lines changed

pkg/tmplexec/generic/exec.go

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package generic
22

33
import (
4-
"strings"
54
"sync/atomic"
65

76
"github.com/projectdiscovery/gologger"
87
"github.com/projectdiscovery/nuclei/v3/pkg/output"
98
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
109
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
10+
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/utils"
1111
mapsutil "github.com/projectdiscovery/utils/maps"
1212
)
1313

@@ -64,17 +64,9 @@ func (g *Generic) ExecuteWithResults(ctx *scan.ScanContext) error {
6464
// ideally this should never happen since protocol exits on error and callback is not called
6565
return
6666
}
67-
ID := req.GetID()
68-
if ID != "" {
69-
builder := &strings.Builder{}
70-
for k, v := range event.InternalEvent {
71-
builder.WriteString(ID)
72-
builder.WriteString("_")
73-
builder.WriteString(k)
74-
_ = previous.Set(builder.String(), v)
75-
builder.Reset()
76-
}
77-
}
67+
68+
utils.FillPreviousEvent(req.GetID(), event, previous)
69+
7870
if event.HasOperatorResult() {
7971
g.results.CompareAndSwap(false, true)
8072
}

pkg/tmplexec/multiproto/multi.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ package multiproto
22

33
import (
44
"strconv"
5-
"strings"
65
"sync/atomic"
76

87
"github.com/projectdiscovery/nuclei/v3/pkg/output"
98
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
109
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
1110
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
1211
"github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
12+
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/utils"
1313
mapsutil "github.com/projectdiscovery/utils/maps"
1414
stringsutil "github.com/projectdiscovery/utils/strings"
1515
)
@@ -90,17 +90,7 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error {
9090
return
9191
}
9292

93-
ID := req.GetID()
94-
if ID != "" {
95-
builder := &strings.Builder{}
96-
for k, v := range event.InternalEvent {
97-
builder.WriteString(ID)
98-
builder.WriteString("_")
99-
builder.WriteString(k)
100-
_ = previous.Set(builder.String(), v)
101-
builder.Reset()
102-
}
103-
}
93+
utils.FillPreviousEvent(req.GetID(), event, previous)
10494

10595
// log event and generate result for the event
10696
ctx.LogEvent(event)

pkg/tmplexec/utils/utils.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package utils
2+
3+
import (
4+
"strings"
5+
6+
"github.com/projectdiscovery/nuclei/v3/pkg/output"
7+
mapsutil "github.com/projectdiscovery/utils/maps"
8+
)
9+
10+
// FillPreviousEvent is a helper function to get the previous event from the event
11+
// without leading to duplicate prefixes
12+
func FillPreviousEvent(reqID string, event *output.InternalWrappedEvent, previous *mapsutil.SyncLockMap[string, any]) {
13+
if reqID == "" {
14+
return
15+
}
16+
17+
for k, v := range event.InternalEvent {
18+
if _, ok := previous.Get(k); ok {
19+
continue
20+
}
21+
22+
if strings.HasPrefix(k, reqID+"_") {
23+
continue
24+
}
25+
26+
var builder strings.Builder
27+
28+
builder.WriteString(reqID)
29+
builder.WriteString("_")
30+
builder.WriteString(k)
31+
32+
_ = previous.Set(builder.String(), v)
33+
}
34+
}

0 commit comments

Comments
 (0)