Fix for int16 overflow bug causing connection to get re-routed to UNIX socket - #747
Merged
Merged
Conversation
Member
|
Thank you for your contribution and detailed explanation of the fix :) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The issue is described in Issue #746. Copying the description here:
Description:
The feature introduced in v-1.17 which enables pgbouncer to round-robin over a comma-separated host list has a bug, which results in connections to a client defined with a host list being re-routed to the UNIX socket path instead (/tmp). Details and repro below:
In the following block of code responsible for parsing the host-list and round-robining across the hosts:
rrcounteris of type int16_t (declaration). This counter is never reset, as a result of which it eventually overflows after32767connections.In the code above, once we overflow, rrcounter effectively becomes negative. At this point, the condition:
server->pool->rrcounter % count == nwill always evaluate to false except for whencount == 1.To understand the issue that follows, consider the following pgbouncer.ini config:
After
32767connections are made to thedatabase-rrclient,rrcounterwill overflow resulting in a negative value. Any following connections todatabase-rrwill result in the conditional noted above to evaluate tofalse, resulting in theforloop to complete leavinghost == nullptr. The assertionAssert(host)will not fire (assuming you don't compile with--enable-cassert).Now that
host == nullptr, the subsequent conditionalif (!host || host[0] == '/' || host[0] == '@')will evaulate totrue, thereby re-routing the connection to the UNIX socket.In the above example, it just so happens that the
dbname==databasefor thedatabase-rrclient matches the client name database. Therefore, when re-routed to the UNIX socket, it will end up getting forwarded to the database client.Assuming we had
database-rras the only client defined, the re-routed connection would fail to connect.Fix:
The fix here is fairly straight-forward- to change
int16_t rrcounter;touint16_t rrcounter;which will prevent overflowing to negative.