Skip to content
  • Sven Sandberg's avatar
    c5cdde55
    BUG#18751585: GTID_SET::GET_STRING_LENGTH GIVES WRONG RESULT AFTER GTID_SET::CLEAR · c5cdde55
    Sven Sandberg authored
    Background:
    GTID sets are stored internally using class Gtid_set, where
    intervals of Gtids are stored using linked lists.
    The member function Gtid_set::to_string returns a string representation
    of the set. The member function Gtid_set::get_string_length returns the
    length of the string, without actually computing the string (this is useful
    so that a caller can allocate a buffer before computing the actual string).
    Gtid_set::get_string_length caches the string length, so that if
    get_string_length is called twice, the length does not need to be recomputed.
    The cached string length is forgotten when the set is modified.
    
    Problem:
    There was one case where we had forgotten to forget the cached string length:
    Gtid_set::clear(). This could cause get_string_length() to return a too big
    number after calling Gtid_set::clear(). This in turn would mean that
    Gtid_set::to_string would allocate more than one byte, set the first byte
    to '\0', leave the rest uninitialized, and return a string length that is
    longer than 0.
    
    Since the generated string is NULL-terminated this did not cause much trouble,
    except in one place: in 5.7,
    performance_schema.replicate_connection_status/RECEIVED_GTID_SET stores a
    Gtid_set in a BLOB column. Since it is a BLOB, it does not count '\0' as
    end-of-string. So it would print all the allocated characters, including
    uninitialized bytes.
    
    Fix:
    Clear Gtid_set::cached_string_length in Gtid_set::clear.
    c5cdde55
    BUG#18751585: GTID_SET::GET_STRING_LENGTH GIVES WRONG RESULT AFTER GTID_SET::CLEAR
    Sven Sandberg authored
    Background:
    GTID sets are stored internally using class Gtid_set, where
    intervals of Gtids are stored using linked lists.
    The member function Gtid_set::to_string returns a string representation
    of the set. The member function Gtid_set::get_string_length returns the
    length of the string, without actually computing the string (this is useful
    so that a caller can allocate a buffer before computing the actual string).
    Gtid_set::get_string_length caches the string length, so that if
    get_string_length is called twice, the length does not need to be recomputed.
    The cached string length is forgotten when the set is modified.
    
    Problem:
    There was one case where we had forgotten to forget the cached string length:
    Gtid_set::clear(). This could cause get_string_length() to return a too big
    number after calling Gtid_set::clear(). This in turn would mean that
    Gtid_set::to_string would allocate more than one byte, set the first byte
    to '\0', leave the rest uninitialized, and return a string length that is
    longer than 0.
    
    Since the generated string is NULL-terminated this did not cause much trouble,
    except in one place: in 5.7,
    performance_schema.replicate_connection_status/RECEIVED_GTID_SET stores a
    Gtid_set in a BLOB column. Since it is a BLOB, it does not count '\0' as
    end-of-string. So it would print all the allocated characters, including
    uninitialized bytes.
    
    Fix:
    Clear Gtid_set::cached_string_length in Gtid_set::clear.
Loading