• Gleb Shchepa's avatar
    Bug #54461: crash with longblob and union or update with subquery · 38165ce4
    Gleb Shchepa authored
    Queries may crash, if
      1) the GREATEST or the LEAST function has a mixed list of
         numeric and LONGBLOB arguments and
      2) the result of such a function goes through an intermediate
         temporary table.
    
    An Item that references a LONGBLOB field has max_length of
    UINT_MAX32 == (2^32 - 1).
    
    The current implementation of GREATEST/LEAST returns REAL
    result for a mixed list of numeric and string arguments (that
    contradicts with the current documentation, this contradiction
    was discussed and it was decided to update the documentation).
    
    The max_length of such a function call was calculated as a
    maximum of argument max_length values (i.e. UINT_MAX32).
    
    That max_length value of UINT_MAX32 was used as a length for
    the intermediate temporary table Field_double to hold
    GREATEST/LEAST function result.
    
    The Field_double::val_str() method call on that field
    allocates a String value.
    
    Since an allocation of String reserves an additional byte
    for a zero-termination, the size of String buffer was
    set to (UINT_MAX32 + 1), that caused an integer overflow:
    actually, an empty buffer of size 0 was allocated.
    
    An initialization of the "first" byte of that zero-size
    buffer with '\0' caused a crash.
    
    The Item_func_min_max::fix_length_and_dec() has been
    modified to calculate max_length for the REAL result like
    we do it for arithmetical operators.
    
    
    ******
    Bug #54461: crash with longblob and union or update with subquery
    
    Queries may crash, if
      1) the GREATEST or the LEAST function has a mixed list of
         numeric and LONGBLOB arguments and
      2) the result of such a function goes through an intermediate
         temporary table.
    
    An Item that references a LONGBLOB field has max_length of
    UINT_MAX32 == (2^32 - 1).
    
    The current implementation of GREATEST/LEAST returns REAL
    result for a mixed list of numeric and string arguments (that
    contradicts with the current documentation, this contradiction
    was discussed and it was decided to update the documentation).
    
    The max_length of such a function call was calculated as a
    maximum of argument max_length values (i.e. UINT_MAX32).
    
    That max_length value of UINT_MAX32 was used as a length for
    the intermediate temporary table Field_double to hold
    GREATEST/LEAST function result.
    
    The Field_double::val_str() method call on that field
    allocates a String value.
    
    Since an allocation of String reserves an additional byte
    for a zero-termination, the size of String buffer was
    set to (UINT_MAX32 + 1), that caused an integer overflow:
    actually, an empty buffer of size 0 was allocated.
    
    An initialization of the "first" byte of that zero-size
    buffer with '\0' caused a crash.
    
    The Item_func_min_max::fix_length_and_dec() has been
    modified to calculate max_length for the REAL result like
    we do it for arithmetical operators.
    38165ce4
item_func.cc 152 KB