-
Notifications
You must be signed in to change notification settings - Fork 366
Prevent panic during TCP EOF (#521) #522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
When performing SNMP over TCP, a panic could have been triggered due to a nil pointer dereference in marshal.go:send(). The following example could have led to a panic: - Perform a GET SNMP request over TCP - Wait for the response in the `waitingResponse` loop - `(*GoSNMP).receive()` returns io.EOF - A new tcp connection will be established successfully via `(*GoSNMP).netConnect` and `err` will be set to `nil` - Break out of the `waitingResponse` loop - `err == nil` and `result == nil`, because latter would be initialized only after a successful `(*GoSNMP).receive()` - Reach the "Success!" point and erroneously `return nil, nil` This will lead to a nil pointer dereference in the calling function `send`. This patch fixes the bug, by actually performing the retry and continuing the outer retry loop. The patch also removes the decrementation of the `retries` counter, as this: > // EOF on TCP: reconnect and retry. Do not count > // as retry as socket was broken is seen a legitimate failed request attempt. Also, remove the decrementation of `retries` here: it could potentially lead to an infinite loop, if reconnecting to the server always succeeds but also always results in an immediate EOF upon receiving the response. Also, ensure that `err` is always set if the `retries` counter exceeds `(*GoSNMP).Retries. The added test is the work of @TimRots. Signed-off-by: Stephan Gabert <stepga@nirgendwo.eu>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of loop goto jumps like this. But I'm guessing we would need some serious refactoring in order to eliminate it.
@@ -202,6 +203,9 @@ func (x *GoSNMP) sendOneRequest(packetOut *SnmpPacket, | |||
break | |||
} | |||
if retries > x.Retries { | |||
if err == nil { | |||
err = fmt.Errorf("max retries (%d) exceeded", x.Retries) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Future improvement idea: Create ErrMaxRetriesExceeded
package var so that errors.Is()
can be used.
For now, this seems fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Future improvement idea: Create
ErrMaxRetriesExceeded
package var so thaterrors.Is()
can be used.For now, this seems fine.
Created issue #523 with your enhancement
When performing SNMP over TCP, a panic could have been triggered due to a nil pointer dereference in marshal.go:send().
The following example could have led to a panic:
waitingResponse
loop(*GoSNMP).receive()
returns io.EOF(*GoSNMP).netConnect
anderr
will be set tonil
waitingResponse
looperr == nil
andresult == nil
, because latter would be initialized only after a successful(*GoSNMP).receive()
return nil, nil
This will lead to a nil pointer dereference in the calling function
send
.This patch fixes the bug, by actually performing the retry and continuing the outer retry loop.
The patch also removes the decrementation of the
retries
counter, as this:is seen a legitimate failed request attempt.
Also, remove the decrementation of
retries
here: it could potentially lead to an infinite loop, if reconnecting to the server always succeeds but also always results in an immediate EOF upon receiving the response.Also, ensure that
err
is always set if theretries
counter exceeds `(*GoSNMP).Retries.