Skip to content
  • gopal.shankar@oracle.com's avatar
    ad70f412
    Bug#13979228 - MEMORY CORRUPTION IN READ_TEXTS() (SQL/DERROR.CC) · ad70f412
    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.
    ad70f412
    Bug#13979228 - MEMORY CORRUPTION IN READ_TEXTS() (SQL/DERROR.CC)
    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.
Loading