Skip to content

refactor: replace Split in loops with more efficient SplitSeq#7278

Open
stringsbuilder wants to merge 4 commits into
projectdiscovery:devfrom
stringsbuilder:dev
Open

refactor: replace Split in loops with more efficient SplitSeq#7278
stringsbuilder wants to merge 4 commits into
projectdiscovery:devfrom
stringsbuilder:dev

Conversation

@stringsbuilder

@stringsbuilder stringsbuilder commented Mar 20, 2026

Copy link
Copy Markdown

Proposed changes

strings.SplitSeq (introduced in Go 1.23) returns a lazy sequence (strings.Seq), allowing gopher to iterate over tokens one by one without creating an intermediate slice.

It significantly reduces memory allocations and can improve performance for long strings.

More info: golang/go#61901

Proof

Checklist

  • Pull request is created against the dev branch
  • All checks passed (lint, unit/integration/regression tests etc.) with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Summary by CodeRabbit

  • Refactor
    • Optimized internal string parsing operations across multiple modules for improved efficiency.

Review Change Stack

Signed-off-by: stringsbuilder <stringsbuilder@outlook.com>
@auto-assign
auto-assign Bot requested a review from dogancanbakir March 20, 2026 11:59
@coderabbitai

coderabbitai Bot commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9a6eea9d-9b9c-4548-a6b2-013b67965df2

📥 Commits

Reviewing files that changed from the base of the PR and between 90cd656 and 0f2565a.

📒 Files selected for processing (1)
  • internal/tests/integration/http_test.go

Walkthrough

This PR migrates string iteration patterns in integration tests from eager-evaluated strings.Split to lazy-evaluated strings.SplitSeq. Five test implementations in http_test.go update their output-line parsing loops while maintaining the same validation and field-extraction logic.

Changes

String Sequence Iterator Refactoring

Layer / File(s) Summary
Integration test port/path parsing iteration updates
internal/tests/integration/http_test.go
Five Execute methods (httpRawUnsafePath, httpPaths, httpVariableDSLFunction, httpRawPathSingleSlash, httpRawUnsafePathSingleSlash) switch from strings.Split(results, "\n") with for _, v := range ... iteration to strings.SplitSeq(results, "\n") with for v := range ... while preserving per-line GET-field extraction and expected/actual validation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 Sequences now lazily flow,
Where splits once eagerly aglow,
Five tests refactored clean and bright,
With iterators lightweight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: replacing strings.Split with strings.SplitSeq throughout multiple files to improve performance.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/protocols/network/network.go (1)

202-213: ⚠️ Potential issue | 🟡 Minor

Trim whitespace before parsing each port token.

Line 206 will reject a common input like port: "80, 443" because the second token still includes leading whitespace.

✂️ Suggested fix
-		for port := range strings.SplitSeq(request.Port, ",") {
+		for rawPort := range strings.SplitSeq(request.Port, ",") {
+			port := strings.TrimSpace(rawPort)
 			if port == "" {
 				continue
 			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/protocols/network/network.go` around lines 202 - 213, When iterating
tokens from strings.SplitSeq(request.Port, ",") trim whitespace from each token
before using it: use a local variable (e.g., tok := strings.TrimSpace(port)),
skip if tok == "", parse tok with strconv.Atoi, validate its range, and append
the trimmed token (tok) to request.ports (not the original port with
whitespace). Update the error messages to include tok where appropriate so
parsing failures reflect the trimmed value; keep references to request.Port,
strings.SplitSeq, strconv.Atoi, and request.ports.
🧹 Nitpick comments (2)
pkg/tmplexec/flow/flow_executor.go (1)

302-311: This still materializes the entire helper file before tokenization.

Line 302's io.ReadAll(reader) dominates the allocation profile here, and the substrings appended in Lines 306-310 keep that full backing string alive. If this path is part of the perf goal, scan the reader directly instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/tmplexec/flow/flow_executor.go` around lines 302 - 311, The code
currently calls io.ReadAll(reader) and then iterates over
strings.SplitSeq(string(bin), "\n"), which materializes the entire reader into
memory and keeps the large backing string alive; replace that pattern by
scanning the reader directly with a bufio.Scanner (or
bufio.Reader.ReadString/ReadBytes loop) to read lines one-by-one from reader,
trim each scanned line (strings.TrimSpace), and append non-empty lines to
values, and if necessary configure Scanner.Buffer to handle long lines; update
the logic that references reader, values, and strings.SplitSeq to use the
scanner instead.
pkg/installer/template.go (1)

568-575: There's still a per-record split allocation in this loop.

Line 570 only needs two fields, but the full split still creates a slice for every checksum entry. A two-part split would align better with the allocation-reduction goal of this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/installer/template.go` around lines 568 - 575, The per-record allocation
comes from using strings.Split on each checksum line (variable v) and assigning
to tmparr; replace that with a two-field split (e.g., strings.SplitN(v, ",", 2)
or better strings.Cut(v, ",")) to avoid allocating a full slice for every entry,
then validate the second field exists before assigning into
allChecksums[tmparr[0]] = tmparr[1] (or using the two return values from
strings.Cut) while keeping the surrounding loop and trimming logic the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@pkg/protocols/network/network.go`:
- Around line 202-213: When iterating tokens from strings.SplitSeq(request.Port,
",") trim whitespace from each token before using it: use a local variable
(e.g., tok := strings.TrimSpace(port)), skip if tok == "", parse tok with
strconv.Atoi, validate its range, and append the trimmed token (tok) to
request.ports (not the original port with whitespace). Update the error messages
to include tok where appropriate so parsing failures reflect the trimmed value;
keep references to request.Port, strings.SplitSeq, strconv.Atoi, and
request.ports.

---

Nitpick comments:
In `@pkg/installer/template.go`:
- Around line 568-575: The per-record allocation comes from using strings.Split
on each checksum line (variable v) and assigning to tmparr; replace that with a
two-field split (e.g., strings.SplitN(v, ",", 2) or better strings.Cut(v, ","))
to avoid allocating a full slice for every entry, then validate the second field
exists before assigning into allChecksums[tmparr[0]] = tmparr[1] (or using the
two return values from strings.Cut) while keeping the surrounding loop and
trimming logic the same.

In `@pkg/tmplexec/flow/flow_executor.go`:
- Around line 302-311: The code currently calls io.ReadAll(reader) and then
iterates over strings.SplitSeq(string(bin), "\n"), which materializes the entire
reader into memory and keeps the large backing string alive; replace that
pattern by scanning the reader directly with a bufio.Scanner (or
bufio.Reader.ReadString/ReadBytes loop) to read lines one-by-one from reader,
trim each scanned line (strings.TrimSpace), and append non-empty lines to
values, and if necessary configure Scanner.Buffer to handle long lines; update
the logic that references reader, values, and strings.SplitSeq to use the
scanner instead.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bb4462ab-2d3f-4a47-917f-e710b053336f

📥 Commits

Reviewing files that changed from the base of the PR and between 0ae6d90 and 90cd656.

📒 Files selected for processing (10)
  • cmd/integration-test/http.go
  • internal/runner/options_test.go
  • pkg/catalog/config/nucleiconfig.go
  • pkg/catalog/config/template.go
  • pkg/installer/template.go
  • pkg/js/devtools/tsgen/parser.go
  • pkg/protocols/javascript/js.go
  • pkg/protocols/network/network.go
  • pkg/testutils/integration.go
  • pkg/tmplexec/flow/flow_executor.go

@neo-by-projectdiscovery-dev

neo-by-projectdiscovery-dev Bot commented Mar 20, 2026

Copy link
Copy Markdown

Neo - PR Security Review

No security issues found

Highlights

  • Refactors strings.Split/Fields to lazy iterator-based strings.SplitSeq/FieldsSeq (Go 1.23)
  • Changes span 10 files: port parsing, path validation, checksum parsing, test utilities, and config parsing
  • All security validations (port validation, path traversal checks) remain functionally identical
Hardening Notes
  • The lazy evaluation in SplitSeq defers memory allocation but does not change iteration logic
  • Port validation in network.go and js.go correctly validates each port with the same checks as before
  • Path traversal prevention in template.go still checks each path component against excluded directories
  • Checksum parsing in installer.go processes trusted local files with the same validation
  • The refactoring reduces memory allocations, which is beneficial for DoS prevention

Comment @pdneo help for available commands. · Open in Neo

@themavik themavik left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SplitSeq/FieldsSeq churn is straightforward. nit: a few call sites still use strings.Split for small inner splits (e.g. installer checksum line) — not wrong, just inconsistent if you are chasing allocs everywhere.

@stringsbuilder

Copy link
Copy Markdown
Author

@Mzack9999 @dogancanbakir Hi, Could you please review this PR at your convenience? Thank you very much.

@Mzack9999

Copy link
Copy Markdown
Member

Holding review until #7419 is merged. The Memoize Functions workflow on contributor forks is auto-pushing a broken regeneration onto any branch named dev (template sentinel for context.Context is stale, ctx ends up in the memoization hash). #7419 fixes the template and scopes the workflow to the upstream repo. Once it lands we'll sync this branch and resume.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants