Skip to content
Open
Changes from all commits
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
2 changes: 1 addition & 1 deletion lib/MySQL_HostGroups_Manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1768,7 +1768,7 @@ void MySQL_HostGroups_Manager::purge_mysql_servers_table() {
for (unsigned int i=0; i<MyHostGroups->len; i++) {
MyHGC *myhgc=(MyHGC *)MyHostGroups->index(i);
MySrvC *mysrvc=NULL;
for (unsigned int j=0; j<myhgc->mysrvs->servers->len; j++) {
for (int j=0; j<myhgc->mysrvs->servers->len; j++) {

Choose a reason for hiding this comment

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

critical

This change correctly identifies the integer underflow issue with j, but the fix introduces a new potential bug. When comparing a signed int (j) with an unsigned int (myhgc->mysrvs->servers->len), the signed integer is promoted to unsigned. If j becomes -1 (after j-- when j was 0), it will be converted to UINT_MAX. The loop condition UINT_MAX < len will then be false, causing the loop to terminate prematurely.

A safer fix is to cast the length to a signed integer to ensure correct comparison. This avoids the signed/unsigned comparison issue.

Alternatively, a more robust and common pattern for removing items from a collection while iterating is to loop backwards. This avoids the need to manually adjust the loop counter (j--). For example:

for (int j = (int)myhgc->mysrvs->servers->len - 1; j >= 0; j--) {
    mysrvc=myhgc->mysrvs->idx(j);
    if (mysrvc->get_status() == MYSQL_SERVER_STATUS_OFFLINE_HARD) {
        if (mysrvc->ConnectionsUsed->conns_length()==0 && mysrvc->ConnectionsFree->conns_length()==0) {
            // no more connections for OFFLINE_HARD server, removing it
            mysrvc=(MySrvC *)myhgc->mysrvs->servers->remove_index_fast(j);
            delete mysrvc;
        }
    }
}

This would require changing the loop body to remove the j-- statement.

for (int j=0; j < (int)myhgc->mysrvs->servers->len; j++) {

Copy link
Author

Choose a reason for hiding this comment

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

No underflow bug occurs because if the variable is decremented, it is incremented before the next comparison, so it has a safe value for an unsigned int before it is promoted in the comparison. It's not my favorite way of doing this, but decrementing the variable in order to increment it later is a pattern that is repeated in several places in the existing code.

In any case, traversing the array in reverse order simplifies the code, so I think it's fine.

mysrvc=myhgc->mysrvs->idx(j);
if (mysrvc->get_status() == MYSQL_SERVER_STATUS_OFFLINE_HARD) {
if (mysrvc->ConnectionsUsed->conns_length()==0 && mysrvc->ConnectionsFree->conns_length()==0) {
Expand Down