Bug #80466 Accessing uninitialized memory os0file.h Encryption(const Encryption&) ~357
Submitted: 22 Feb 2016 5:04 Modified: 22 Feb 2016 12:57
Reporter: Sergey Sprogis Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Compiling Severity:S3 (Non-critical)
Version:5.7.10 OS:Solaris (Sparc, 11.3)
Assigned to: CPU Architecture:Any

[22 Feb 2016 5:04] Sergey Sprogis
Description:
Oracle's tool called Discover detects UMR (Uninitialized Memory Read)
in mysqld server when executing '1st' test case located inside
MySQL 5.7.10. This UMR was produced on Sparc Solaris 11.3 T7 system,
but it's not platform specific, and can occur on any other platform.

Error message and call stack reported by Discover looks like this:
======================================
(UMR): accessing uninitialized data ... (8 bytes) on the stack:
 Encryption::Encryption(const Encryption&) + 0x2c8 <os0file.h : 357>
  357:=> m_key(other.m_key),
 os_file_io(const IORequest&, int, void* ... <os0file.cc : 5345>
  5345:=>  IORequest       type = in_type;
 os_file_pread(IORequest&, int, void*, ... <os0file.cc : 5566>
  5566:=>  ssize_t n_bytes = os_file_io(type, file, buf, n, offset, err);
 os_file_read_page(IORequest&, int, void*, ... <os0file.cc : 5605>
  5605:=>  n_bytes = os_file_pread(type, file, buf, n, offset, &err);
 os_file_read_no_error_handling_func(IORequest&, ... <os0file.cc : 6023>
  6023:=>  return(os_file_read_page(type, file, buf, offset, n, o, false));
 pfs_os_file_read_no_error_handling_func(IORequest&, ... <os0file.ic : 332>
  332:=>  type, file, buf, offset, n, o);
 Datafile::read_first_page(bool) + 0xae8 <fsp0file.cc : 342>
  342:=>  request, m_handle, m_first_page, 0, page_size, &n_read);
======================================

How to repeat:
1. If you have access to Discover tool, and latest Sun Studio C/C++ compilers
   you need to build MySQL-5.7.10 sources in debug mode on Solaris Sparc,
   then launch discover binary with input argument as mysqld binary,
   and when completed to take a look inside mysql.html file which should
   contain call stack shown in description above.

2. If you do not have access to Discover, you need to debug MySQL server
   with '1st' test case, and to see  other.m_key, other.m_klen other.m_iv operands located
   inside storage/innobase/include/os0file.h lines ~357-359

    m_key(other.m_key),
    m_klen(other.m_klen),
    m_iv(other.m_iv)

   are indeed uninitialized before that point.

   Below is 35 lines independent executable t.cc test case which accurately
   simulates original issue. For it Discover produces exactly the same UMR
   message as for original mysqld server.

t.cc
===================================
typedef char byte;
typedef unsigned long ulint;
typedef unsigned short uint16_t;
struct Encryption {
 enum Type {NONE=0,AES=1};
 Encryption()
  : m_type(NONE)
 {};
 Encryption(const Encryption& other)
  : m_type(other.m_type),
    m_key(other.m_key),
    m_klen(other.m_klen),
    m_iv(other.m_iv)
 {}
 Type m_type;
 byte* m_key;
 ulint m_klen;
 byte* m_iv;
};
class IORequest {
 public:
  enum {READ=1,WRITE=2};
  explicit IORequest(ulint type) { }
 private:
  Encryption m_encryption;
  uint16_t m_type;
};
void os_file_io(const IORequest &in_type) {
 IORequest type=in_type;
}
int main () {
 IORequest request(IORequest::WRITE);
 os_file_io(request);
 return 0;
}
===================================

Suggested fix:
Somehow initialize other.m_key, other.m_klen other.m_iv operands before their readis inside:
    m_key(other.m_key), m_klen(other.m_klen), m_iv(other.m_iv)
[22 Feb 2016 12:57] MySQL Verification Team
Hello Sergey,

Thank you for the report!

Thanks,
Umesh