Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,14 @@ func (r *Runner) normalizeAndQueueInputs(inputs chan taskInput) error {
for scanner.Scan() {
text := scanner.Text()
if text != "" {
r.processInputItem(text, inputs)
// Split comma-separated values to match -u flag behavior
items := strings.Split(text, ",")
for _, item := range items {
item = strings.TrimSpace(item)
if item != "" {
r.processInputItem(item, inputs)
}
}
}
}
}
Expand All @@ -449,7 +456,14 @@ func (r *Runner) normalizeAndQueueInputs(inputs chan taskInput) error {
for scanner.Scan() {
text := scanner.Text()
if text != "" {
r.processInputItem(text, inputs)
// Split comma-separated values to match -u flag behavior
items := strings.Split(text, ",")
for _, item := range items {
item = strings.TrimSpace(item)
if item != "" {
r.processInputItem(item, inputs)
}
}
}
}
}
Expand Down
167 changes: 167 additions & 0 deletions internal/runner/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,173 @@ func getTaskInputFromFile(filename string, ports []string) ([]taskInput, error)
return ret, nil
}

func Test_CommaSeparatedInputFile(t *testing.T) {
// Create a temporary file with comma-separated inputs
tempFile, err := os.CreateTemp("", "tlsx-test-*.txt")
require.NoError(t, err)
defer os.Remove(tempFile.Name())

// Write comma-separated prefixes to the file
content := "192.168.1.0/24,192.168.2.0/24,192.168.3.0/24\n"
_, err = tempFile.WriteString(content)
require.NoError(t, err)
tempFile.Close()

options := &clients.Options{
Ports: []string{"443"},
InputList: tempFile.Name(),
}
runner := &Runner{options: options}

inputs := make(chan taskInput, 100)

// Test normalizeAndQueueInputs with the file
go func() {
err := runner.normalizeAndQueueInputs(inputs)
require.NoError(t, err)
close(inputs)
}()
Comment on lines +232 to +236
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid require.NoError inside goroutines - test will panic on failure.

The same pattern that was fixed in Test_CommaSeparatedStdin should be applied here. Calling require.NoError from a non-test goroutine invokes t.FailNow(), which must only be called from the test goroutine per Go's testing package documentation.

🔧 Proposed fix using error channel pattern
 	inputs := make(chan taskInput, 100)
 	
 	// Test normalizeAndQueueInputs with the file
+	errCh := make(chan error, 1)
 	go func() {
-		err := runner.normalizeAndQueueInputs(inputs)
-		require.NoError(t, err)
+		errCh <- runner.normalizeAndQueueInputs(inputs)
 		close(inputs)
 	}()

 	var got []taskInput
 	for task := range inputs {
 		got = append(got, task)
 	}
+
+	require.NoError(t, <-errCh, "normalizeAndQueueInputs failed")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runner/runner_test.go` around lines 232 - 236, The goroutine in the
test calls require.NoError from a non-test goroutine (inside the anonymous go
func wrapping runner.normalizeAndQueueInputs(inputs)), which can panic; change
this to use an error channel: create a chan error, run
normalizeAndQueueInputs(inputs) in the goroutine and send its returned error (or
nil) on the channel, then in the main test goroutine receive from that channel
and call require.NoError on the received error; ensure you still close(inputs)
appropriately after calling normalizeAndQueueInputs or from the goroutine before
sending the error so the test behavior remains the same.


var got []taskInput
for task := range inputs {
got = append(got, task)
}

// We expect 3 CIDR ranges, each expanding to 256 IPs
// But for testing purposes, we just verify that we got multiple inputs
// and that they start with the expected prefixes
require.Greater(t, len(got), 0, "should have processed inputs from comma-separated file")

// Check that we have inputs from all three prefixes
hasFirstPrefix := false
hasSecondPrefix := false
hasThirdPrefix := false

for _, task := range got {
if strings.HasPrefix(task.host, "192.168.1.") {
hasFirstPrefix = true
}
if strings.HasPrefix(task.host, "192.168.2.") {
hasSecondPrefix = true
}
if strings.HasPrefix(task.host, "192.168.3.") {
hasThirdPrefix = true
}
}

assert.True(t, hasFirstPrefix, "should have inputs from first prefix")
assert.True(t, hasSecondPrefix, "should have inputs from second prefix")
assert.True(t, hasThirdPrefix, "should have inputs from third prefix")
}

func Test_CommaSeparatedInputFileWithWhitespace(t *testing.T) {
// Create a temporary file with comma-separated inputs with whitespace
tempFile, err := os.CreateTemp("", "tlsx-test-whitespace-*.txt")
require.NoError(t, err)
defer os.Remove(tempFile.Name())

// Write comma-separated prefixes with whitespace to the file
content := "192.168.1.0/24, 192.168.2.0/24 , 192.168.3.0/24\n"
_, err = tempFile.WriteString(content)
require.NoError(t, err)
tempFile.Close()

options := &clients.Options{
Ports: []string{"443"},
InputList: tempFile.Name(),
}
runner := &Runner{options: options}

inputs := make(chan taskInput, 100)

// Test normalizeAndQueueInputs with the file
go func() {
err := runner.normalizeAndQueueInputs(inputs)
require.NoError(t, err)
close(inputs)
}()
Comment on lines +291 to +295
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same goroutine assertion issue as Test_CommaSeparatedInputFile.

Apply the error channel pattern here as well for consistency and test robustness.

🔧 Proposed fix
 	inputs := make(chan taskInput, 100)
 	
 	// Test normalizeAndQueueInputs with the file
+	errCh := make(chan error, 1)
 	go func() {
-		err := runner.normalizeAndQueueInputs(inputs)
-		require.NoError(t, err)
+		errCh <- runner.normalizeAndQueueInputs(inputs)
 		close(inputs)
 	}()

 	var got []taskInput
 	for task := range inputs {
 		got = append(got, task)
 	}
+
+	require.NoError(t, <-errCh, "normalizeAndQueueInputs failed")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
go func() {
err := runner.normalizeAndQueueInputs(inputs)
require.NoError(t, err)
close(inputs)
}()
inputs := make(chan taskInput, 100)
// Test normalizeAndQueueInputs with the file
errCh := make(chan error, 1)
go func() {
errCh <- runner.normalizeAndQueueInputs(inputs)
close(inputs)
}()
var got []taskInput
for task := range inputs {
got = append(got, task)
}
require.NoError(t, <-errCh, "normalizeAndQueueInputs failed")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runner/runner_test.go` around lines 291 - 295, The test spawns a
goroutine calling runner.normalizeAndQueueInputs(inputs) but asserts directly in
the goroutine; change it to use the error-channel pattern: create a channel
(e.g. errCh), run the goroutine to call runner.normalizeAndQueueInputs(inputs)
and send the returned error on errCh, then close inputs, and in the main test
goroutine receive from errCh and assert require.NoError(t, err). This mirrors
the fix used in Test_CommaSeparatedInputFile and ensures the assertion is
performed in the test goroutine.


var got []taskInput
for task := range inputs {
got = append(got, task)
}

// Check that whitespace was trimmed and all prefixes were processed
hasFirstPrefix := false
hasSecondPrefix := false
hasThirdPrefix := false

for _, task := range got {
if strings.HasPrefix(task.host, "192.168.1.") {
hasFirstPrefix = true
}
if strings.HasPrefix(task.host, "192.168.2.") {
hasSecondPrefix = true
}
if strings.HasPrefix(task.host, "192.168.3.") {
hasThirdPrefix = true
}
}

assert.True(t, hasFirstPrefix, "should have inputs from first prefix")
assert.True(t, hasSecondPrefix, "should have inputs from second prefix")
assert.True(t, hasThirdPrefix, "should have inputs from third prefix")
}

func Test_CommaSeparatedStdin(t *testing.T) {
// Test comma-separated values from stdin
oldStdin := os.Stdin
r, w, _ := os.Pipe()
os.Stdin = r

// Write comma-separated input to stdin
go func() {
_, err := w.WriteString("192.168.1.0/24,192.168.2.0/24\n")
require.NoError(t, err)
w.Close()
}()

options := &clients.Options{
Ports: []string{"443"},
}
runner := &Runner{options: options}
runner.hasStdin = true
runner.hasStdinSet = true

inputs := make(chan taskInput, 100)

// Test normalizeAndQueueInputs with stdin
go func() {
err := runner.normalizeAndQueueInputs(inputs)
require.NoError(t, err)
close(inputs)
}()

var got []taskInput
for task := range inputs {
got = append(got, task)
}

// Restore stdin
os.Stdin = oldStdin

// Check that both prefixes were processed
hasFirstPrefix := false
hasSecondPrefix := false

for _, task := range got {
if strings.HasPrefix(task.host, "192.168.1.") {
hasFirstPrefix = true
}
if strings.HasPrefix(task.host, "192.168.2.") {
hasSecondPrefix = true
}
}

assert.True(t, hasFirstPrefix, "should have inputs from first prefix")
assert.True(t, hasSecondPrefix, "should have inputs from second prefix")
}

func Test_CTLogsModeValidation(t *testing.T) {
// Test that CT logs mode and input mode cannot be used together
// This validation is now done in the main package, so this test should be removed
Expand Down