-
gopal.shankar@oracle.com authored
PROBLEM: -------- The following command could cause mysqld to crash. mysql> set LC_TIME_NAMES='ru_RU'; The problem is seen only when there are more new error messages are added to sql/share/errmsg-utf8.txt, before compilation. ANALYSIS:- ---------- errmsg-utf8.txt contains all the error messages. For faster access errmsg.sys files are created for each language. The errmsg.sys file has following file format. -------------------------------------------------------------- Current errmsg.sys File Format: -------------------------------------------------------------- SECTION1: Header=32 bytes, length = (uint16) of byte 6 & 7 count = (uint16) of byte 8 & 9 SECTION2: Array of offset pointer to messages= count*2 bytes Every 2 bytes [after header, until header_size+count*2] contains offset of error message in the errmsg.sys file. These offsets point to section3. SECTION3: All error messages, each one is null terminated. -------------------------------------------------------------- PROBLEM1) With the current file format, the length of SECTION3 is stored in errmsg.sys file header byte 6 and 7. These 2 bytes can hold maximum size of section till 2^16 = 64k. If the SECTION3 increases in size more than 64K, then these two bytes in header are not enough to hold the size. PROBLEM2) As the number of error message increase, the SECTION3 grows. Consequently, error messages could be places at offset greater than 2^16=64K. SECTION2 contains offsets that point to start of each error messages in SECTION3. If the error message is stored past 64K size in SECTION3, then the 2 bytes element in offset array of SECTION2 will not be sufficient to store the offset. Above two problems might cause server to read invalid 'length'/'offset'. Due to which the code would write bytes more than allocated. FIX: ---- Both of above mentioned problems, demand increase in number of bytes to hold the length (also count) of SECTION3 and offsets in SECTION2. Following changes in existing file format would solve the problem. Note that the header currently has many unused bytes, so using more bytes for length and count is not a problem. -------------------------------------------------------------- New errmsg.sys File Format: -------------------------------------------------------------- SECTION1: Header=32 bytes, length = (uint32) of byte 6 to 10 count = (uint32) of byte 10 to 14 SECTION2: Array of offset pointer to messages= count*4 bytes Every 4 bytes [after header, until header_size+count*4] contains offset of error message in the errmsg.sys file. These offsets point to SECTION3. SECTION3: All error messages, each one is null terminated. -------------------------------------------------------------- With the new changes to file format, the length, count in header and offset array in SECTION2 are now 4bytes instead of 2bytes. Hence, the errmsg.sys can can now grow upto 4GB (currently its 64K), which seem to be too-much-of-memory for error messages. Each errmsg.sys has version associated with it. Version is stored at 3rd byte from begining of errmsg.sys. The current version of file is '2' and the new version will be '3'. If new mysql binary tries to use old errmsg.sys, we report an error. TESTING: -------- This bug depends on number of messages in sql/share/errmsg-utf8.txt. As the size of errmsg.sys keeps changing over time, its hard to write test case based on it.
gopal.shankar@oracle.com authoredPROBLEM: -------- The following command could cause mysqld to crash. mysql> set LC_TIME_NAMES='ru_RU'; The problem is seen only when there are more new error messages are added to sql/share/errmsg-utf8.txt, before compilation. ANALYSIS:- ---------- errmsg-utf8.txt contains all the error messages. For faster access errmsg.sys files are created for each language. The errmsg.sys file has following file format. -------------------------------------------------------------- Current errmsg.sys File Format: -------------------------------------------------------------- SECTION1: Header=32 bytes, length = (uint16) of byte 6 & 7 count = (uint16) of byte 8 & 9 SECTION2: Array of offset pointer to messages= count*2 bytes Every 2 bytes [after header, until header_size+count*2] contains offset of error message in the errmsg.sys file. These offsets point to section3. SECTION3: All error messages, each one is null terminated. -------------------------------------------------------------- PROBLEM1) With the current file format, the length of SECTION3 is stored in errmsg.sys file header byte 6 and 7. These 2 bytes can hold maximum size of section till 2^16 = 64k. If the SECTION3 increases in size more than 64K, then these two bytes in header are not enough to hold the size. PROBLEM2) As the number of error message increase, the SECTION3 grows. Consequently, error messages could be places at offset greater than 2^16=64K. SECTION2 contains offsets that point to start of each error messages in SECTION3. If the error message is stored past 64K size in SECTION3, then the 2 bytes element in offset array of SECTION2 will not be sufficient to store the offset. Above two problems might cause server to read invalid 'length'/'offset'. Due to which the code would write bytes more than allocated. FIX: ---- Both of above mentioned problems, demand increase in number of bytes to hold the length (also count) of SECTION3 and offsets in SECTION2. Following changes in existing file format would solve the problem. Note that the header currently has many unused bytes, so using more bytes for length and count is not a problem. -------------------------------------------------------------- New errmsg.sys File Format: -------------------------------------------------------------- SECTION1: Header=32 bytes, length = (uint32) of byte 6 to 10 count = (uint32) of byte 10 to 14 SECTION2: Array of offset pointer to messages= count*4 bytes Every 4 bytes [after header, until header_size+count*4] contains offset of error message in the errmsg.sys file. These offsets point to SECTION3. SECTION3: All error messages, each one is null terminated. -------------------------------------------------------------- With the new changes to file format, the length, count in header and offset array in SECTION2 are now 4bytes instead of 2bytes. Hence, the errmsg.sys can can now grow upto 4GB (currently its 64K), which seem to be too-much-of-memory for error messages. Each errmsg.sys has version associated with it. Version is stored at 3rd byte from begining of errmsg.sys. The current version of file is '2' and the new version will be '3'. If new mysql binary tries to use old errmsg.sys, we report an error. TESTING: -------- This bug depends on number of messages in sql/share/errmsg-utf8.txt. As the size of errmsg.sys keeps changing over time, its hard to write test case based on it.
Loading