RPM Community Forums

Mailing List Message of <rpm-devel>

rpmdbNextIterator infinite loop

From: Alexey Tourbin <at@altlinux.ru>
Date: Sun 24 Aug 2008 - 16:27:21 CEST
Message-ID: <20080824142721.GA6477@altlinux.org>
rpmdb/rpmdb.c (rpmdbNextIterator):
  2381  top:
  2382      uh = NULL;
  2383      uhlen = 0;
  2384  
  2385      do {
  2386  union _dbswap mi_offset;
  2387  
  2388          if (mi->mi_set) {
  2389              if (!(mi->mi_setx < mi->mi_set->count))
  2390                  return NULL;
  2391              mi->mi_offset = dbiIndexRecordOffset(mi->mi_set, mi->mi_setx);
  2392              mi->mi_filenum = dbiIndexRecordFileNumber(mi->mi_set, mi->mi_setx);
  2393  mi_offset.ui = mi->mi_offset;
  2394  if (dbiByteSwapped(dbi) == 1)
  2395      _DBSWAP(mi_offset);
  2396              keyp = &mi_offset;
  2397              keylen = sizeof(mi_offset.ui);
  2398          } else {
* 2399              key->data = (void *)mi->mi_keyp;
  2400              key->size = (UINT32_T) mi->mi_keylen;
  2401              data->data = uh;
  2402              data->size = (UINT32_T) uhlen;
  2403  #if !defined(_USE_COPY_LOAD)
  2404              data->flags |= DB_DBT_MALLOC;
  2405  #endif
  2406              rc = dbiGet(dbi, mi->mi_dbc, key, data,
  2407                          (key->data == NULL ? DB_NEXT : DB_SET));
  2408              data->flags = 0;
  2409              keyp = key->data;
  2410              keylen = key->size;
  2411              uh = data->data;
  2412              uhlen = data->size;
  2413  
  2414              /*
  2415               * If we got the next key, save the header instance number.
  2416               *
  2417               * For db3 Packages, instance 0 (i.e. mi->mi_setx == 0) is the
  2418               * largest header instance in the database, and should be
  2419               * skipped.
  2420               */
  2421              if (keyp && mi->mi_setx && rc == 0) {
  2422                  memcpy(&mi_offset, keyp, sizeof(mi_offset.ui));
  2423  if (dbiByteSwapped(dbi) == 1)
  2424      _DBSWAP(mi_offset);
  2425                  mi->mi_offset = (unsigned) mi_offset.ui;
  2426              }
  2427  
  2428              /* Terminate on error or end of keys */
  2429  /*@-compmempass@*/
  2430              if (rc || (mi->mi_setx && mi->mi_offset == 0))
  2431                  return NULL;
  2432  /*@=compmempass@*/
  2433  #ifdef  REFERENCE
  2434  if (mi->mi_offset & 0xffff0000) {
  2435  fprintf(stderr, "*** damaged key 0x%x reset to 0\n", mi->mi_offset);
  2436  mi->mi_offset = 0;
  2437  }
  2438  #endif
  2439          }
  2440          mi->mi_setx++;
  2441      } while (mi->mi_offset == 0);
...
  2532      if (mi->mi_h == NULL || !headerIsEntry(mi->mi_h, RPMTAG_NAME)) {
  2533          rpmlog(RPMLOG_ERR,
  2534                  _("rpmdb: damaged header #%u retrieved -- skipping.\n"),
  2535                  mi->mi_offset);
* 2536          goto top;
  2537      }

This code is subject to infinite loop.
Consider how it is called:

	mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, hdrNum, sizeof(hdrNum));
	h = rpmdbNextIterator(mi);

and consider that the header indentified with hdrNum is damaged.
What happens then?  In line 2536, you "goto top".  And on top,
mi->mi_set is epmty (because it is not index-to-join-key lookup),
and key->data is hdrNum.  This means that dbiGet gets called with
DB_SET, you get the same header which is damaged etc.

(I'll try to fix this but I'm not sure what's the best way to fix
this yet.)


  • application/pgp-signature attachment: stored
Received on Sun Aug 24 16:27:23 2008
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.