node_load() does a query with "FROM {node} n INNER JOIN {users} u ON u.uid = n.uid".
As a consequence, it will return FALSE if the node author does not exist.

_node_update_index() does not check if node_load() was successful.

-----

Why is this a problem?

Tried this on D6:
drush cron
Invalid argument supplied for foreach() in ../taxonomy.module

stack trace:
- taxonomy_node_update_index(&$node)
- taxonomy_nodeapi()
- node_invoke_nodeapi()
- _node_index_node()
- node_update_index()
- module_invoke('node', 'update_index')
- search_cron()

The problem begins when node_update_index() does this query:
"SELECT n.nid FROM {node} n ..."
with no check if the author exists or not.
Then _node_update_index() calls node_load(), which returns FALSE.
Then _node_update_index() does $node->build_mode = NODE_BUILD_SEARCH_INDEX;, which turns the FALSE value into an object (with only one attribute).
Then _node_update_index() calls node_build_content() and node_invoke_nodeapi(), with a node that does not exist.

-----

I'm not sure whether this has to be fixed in node_load() or in _node_update_index(),
or if the database is considered broken if a node author does not exist.

Comments

donquixote’s picture

Version: 7.x-dev » 6.x-dev

D7 uses NodeController::load() instead of node_load(), and I have not checked if this has the same effect.

Status: Active » Closed (outdated)

Automatically closed because Drupal 6 is no longer supported. If the issue verifiably applies to later versions, please reopen with details and update the version.

jwilson3’s picture

Issue summary: View changes

I hit this issue on a legacy drupal 6 site. had to write a drush script to fix it. YMMV.


// mymodule.drush.inc  (written for drush 6 compatibility in mind)
/**
 * Implements hook_drush_command().
 */
function mymodule_drush_command() {
  $items['content-reassign'] = array(
    'description' => 'Reassign nodes to a specific user account when the node is owned by a user id that has been deleted.',
    'callback' => 'mymodule_content_reassign',
    'arguments' => array(
      'uid' => dt('A valid user id.'),
    ),
    'drupal dependencies' => array('node', 'user'),
  );
  return $items;
}

function mymodule_content_reassign($uid = 1) {
  $sql = "SELECT n.nid, n.uid FROM {node} n LEFT JOIN {users} u ON n.uid = u.uid WHERE u.uid IS NULL ORDER BY n.nid ASC";
  $result = db_query($sql);

  while ($node = db_fetch_object($result)) {
    $sql = "UPDATE {node} SET uid = %d WHERE nid = %d";
    db_query($sql, $uid, $node->nid);
    $count = db_affected_rows();
    if ($count == 1) {
      drush_print(dt('Updated node @nid’s owner from @old to @new.', array('@nid' => $node->nid, '@old' => $node->uid, '@new' => $uid)));
    }
  }
}