-
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.
Sven Sandberg authoredBackground: 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