Bug #22694 function plugin_foreach_with_mask() uses an uninitialized pointer
Submitted: 26 Sep 2006 7:20 Modified: 3 Jan 2007 11:28
Reporter: Paul McCullagh (Basic Quality Contributor) (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S1 (Critical)
Version:5.1.12-BK OS:
Assigned to: Antony Curtis CPU Architecture:Any
Tags: plugin, plugin_foreach_with_mask, pointer, uninitialized

[26 Sep 2006 7:20] Paul McCullagh
Description:
The function plugin_foreach_with_mask() in file sql_plugin.cc uses an uninitialized pointer after an engine plug-in is loaded on startup of MySQL.

As far as I can tell, the following line:

    plugins=(struct st_plugin_int **)my_alloca(total*sizeof(*plugins));

does not zero out the allocated memory.

This means that the code:

      if (plugin->state & state_mask)
        continue;
      plugins[idx]= plugin;

does not initialize the idx pointer when the condition holds, i.e. the element plugins[idx] remains uninitialized.

Later in the function the following code uses the uninitialized pointer:

  for (idx= 0; idx < total; idx++)
  {
    plugin= plugins[idx];
    ....
    if (plugin && func(thd, plugin, arg))
        goto err;
  }

How to repeat:
I repeated this error by starting MySQL and installing a plug-in:

INSTALL PLUGIN pbxt SONAME 'libpbxt.so';

Then, on restart of MySQL the error will occur. In this case plugin_foreach_with_mask() is called shortly after plugin_add() while the plugin is still in the PLUGIN_IS_UNINITIALIZED state.

Suggested fix:
Inititialize the memory to zero on allocation, or do it as follows:

      if (plugin->state & state_mask)
      {
         plugins[idx]= 0;
        continue;
      }
[26 Sep 2006 18:12] Valeriy Kravchuk
Thank you for a problem report. In latest 5.1.12-BK the code is still the same:

my_bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
                       int type, uint state_mask, void *arg)
{
  uint idx, total;
  struct st_plugin_int *plugin, **plugins;
  int version=plugin_array_version;
  DBUG_ENTER("plugin_foreach_with_mask");

  state_mask= ~state_mask; // do it only once

  rw_rdlock(&THR_LOCK_plugin);
  if (type == MYSQL_ANY_PLUGIN)
  {
    total=plugin_array.elements;
    plugins=(struct st_plugin_int **)my_alloca(total*sizeof(*plugins));
    for (idx= 0; idx < total; idx++)
    {
      plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
      if (plugin->state & state_mask)
        continue;
      plugins[idx]= plugin;
    }
  }
...

So, it looks like a potential bug, as demonstrated with your test.
[24 Oct 2006 23:43] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/14313

ChangeSet@1.2321, 2006-10-24 16:41:13-07:00, acurtis@xiphis.org +1 -0
  Bug#22694
    "function plugin_foreach_with_mask() uses an uninitialized pointer"
    Fix uninitialized memory.
[7 Nov 2006 10:32] Antony Curtis
pushed to 5.1-engines tree
[22 Dec 2006 11:13] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/17318

ChangeSet@1.2357, 2006-12-22 12:12:58+01:00, msvensson@pilot.mysql.com +1 -0
  Bug#22694 "function plugin_foreach_with_mask() uses an uninitialized pointer"
     Fix uninitialized memory.
[27 Dec 2006 0:14] Antony Curtis
Pushed to 5.1.15-beta repository
[3 Jan 2007 11:28] Jon Stephens
Thank you for your bug report. This issue has been committed to our source repository of that product and will be incorporated into the next release.

If necessary, you can access the source repository and build the latest available version, including the bug fix. More information about accessing the source trees is available at

    http://dev.mysql.com/doc/en/installing-source.html

Documented bugfix in 5.1.15 changelog.