fix: prevent segfault if malicious server sends 1 GB of data through ftpNLST.
authorjbj <devnull@localhost>
Tue, 8 Apr 2003 21:42:55 +0000 (21:42 +0000)
committerjbj <devnull@localhost>
Tue, 8 Apr 2003 21:42:55 +0000 (21:42 +0000)
fix: rpmal could segfault under obscure conditions.
Use array, not individual structures, for rpmsw{Enter,Exit} timestamps.

CVS patchset: 6735
CVS date: 2003/04/08 21:42:55

16 files changed:
lib/depends.c
lib/fsm.c
lib/package.c
lib/psm.c
lib/rpmal.c
lib/rpmte.c
lib/rpmts.c
lib/rpmts.h
lib/signature.c
lib/transaction.c
rpmdb/rpmdb.c
rpmdb/rpmdb.h
rpmio/rpmio_internal.h
rpmio/rpmrpc.c
rpmio/rpmsw.c
rpmio/rpmsw.h

index 9fdbfa7..ea0be77 100644 (file)
@@ -1002,8 +1002,8 @@ static inline int addRelation(rpmts ts,
                /*@dependent@*/ rpmte p,
                unsigned char * selected,
                rpmds requires)
-       /*@globals fileSystem @*/
-       /*@modifies ts, p, *selected, fileSystem @*/
+       /*@globals fileSystem, internalState @*/
+       /*@modifies ts, p, *selected, fileSystem, internalState @*/
 {
     rpmtsi qi; rpmte q;
     tsortInfo tsi;
@@ -1179,7 +1179,7 @@ int rpmtsOrder(rpmts ts)
     rpmalMakeIndex(ts->addedPackages);
 #endif
 
-    (void) rpmswEnter(&ts->op_order, 0);
+    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
 
     /* T1. Initialize. */
     if (oType == 0)
@@ -1582,7 +1582,7 @@ assert(newOrderCount == ts->orderCount);
 #endif
     freeBadDeps();
 
-    (void) rpmswExit(&ts->op_order, 0);
+    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
 
     return 0;
 }
@@ -1597,7 +1597,7 @@ int rpmtsCheck(rpmts ts)
     int xx;
     int rc;
 
-    (void) rpmswEnter(&ts->op_check, 0);
+    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
 
     /* Do lazy, readonly, open of rpm database. */
     if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) {
@@ -1724,7 +1724,7 @@ exit:
     mi = rpmdbFreeIterator(mi);
     pi = rpmtsiFree(pi);
 
-    rpmswExit(&ts->op_check, 0);
+    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
 
     /*@-branchstate@*/
     if (closeatexit)
index 5618dc8..d8e8533 100644 (file)
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -18,7 +18,6 @@
 #define        _RPMFI_INTERNAL
 #include "rpmfi.h"
 #include "rpmte.h"
-#define        _RPMTS_INTERNAL
 #include "rpmts.h"
 #include "rpmsq.h"
 
@@ -115,7 +114,9 @@ static /*@null@*/ void * mapFreeIterator(/*@only@*//*@null@*/ void * p)
 {
     FSMI_t iter = p;
     if (iter) {
+/*@-internalglobs@*/ /* XXX rpmswExit() */
        iter->ts = rpmtsFree(iter->ts);
+/*@=internalglobs@*/
        iter->fi = rpmfiUnlink(iter->fi, "mapIterator");
     }
     return _free(p);
@@ -2303,11 +2304,8 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break;
        if (fsm->rfd != NULL) {
            if (_fsm_debug && (stage & FSM_SYSCALL))
                rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->rfd);
-           if (fsm->rfd->stats != NULL) {
-               FDSTAT_t stats = fsm->rfd->stats;
-               rpmts ts = fsmGetTs(fsm);
-               (void) rpmswAdd(&ts->op_digest, &stats->ops[FDSTAT_DIGEST]);
-            }
+           (void) rpmswAdd(rpmtsOp(fsmGetTs(fsm), RPMTS_OP_DIGEST),
+                       fdstat_op(fsm->rfd, FDSTAT_DIGEST));
            (void) Fclose(fsm->rfd);
            errno = saveerrno;
        }
@@ -2336,11 +2334,8 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break;
        if (fsm->wfd != NULL) {
            if (_fsm_debug && (stage & FSM_SYSCALL))
                rpmMessage(RPMMESS_DEBUG, " %8s (%p)\n", cur, fsm->wfd);
-           if (fsm->wfd->stats != NULL) {
-               FDSTAT_t stats = fsm->wfd->stats;
-               rpmts ts = fsmGetTs(fsm);
-               (void) rpmswAdd(&ts->op_digest, &stats->ops[FDSTAT_DIGEST]);
-            }
+           (void) rpmswAdd(rpmtsOp(fsmGetTs(fsm), RPMTS_OP_DIGEST),
+                       fdstat_op(fsm->wfd, FDSTAT_DIGEST));
            (void) Fclose(fsm->wfd);
            errno = saveerrno;
        }
index 5871629..e2da6ad 100644 (file)
@@ -9,7 +9,6 @@
 #include <rpmio_internal.h>
 #include <rpmlib.h>
 
-#define        _RPMTS_INTERNAL
 #include "rpmts.h"
 
 #include "misc.h"      /* XXX stripTrailingChar() */
@@ -543,7 +542,7 @@ verifyinfo_exit:
        ildl[1] = (regionEnd - dataStart);
        ildl[1] = htonl(ildl[1]);
 
-       (void) rpmswEnter(&ts->op_digest, 0);
+       (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
        dig->hdrmd5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
 
        b = (unsigned char *) header_magic;
@@ -565,7 +564,7 @@ verifyinfo_exit:
        nb = htonl(ildl[1]);
         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
         dig->nbytes += nb;
-       (void) rpmswExit(&ts->op_digest, dig->nbytes);
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
 
        break;
 #endif
@@ -588,7 +587,7 @@ verifyinfo_exit:
        ildl[1] = htonl(ildl[1]);
 /*@=boundswrite@*/
 
-       (void) rpmswEnter(&ts->op_digest, 0);
+       (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
        dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
 
        b = (unsigned char *) header_magic;
@@ -610,7 +609,7 @@ verifyinfo_exit:
        nb = htonl(ildl[1]);
         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
         dig->nbytes += nb;
-       (void) rpmswExit(&ts->op_digest, dig->nbytes);
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
 
        break;
     default:
index f0f77d2..bc2169e 100644 (file)
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -474,7 +474,7 @@ static pid_t psmWait(rpmpsm psm)
 
     (void) rpmsqWait(&psm->sq);
     msecs = psm->sq.op.usecs/1000;
-    (void) rpmswAdd(&ts->op_scriptlets, &psm->sq.op);
+    (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), &psm->sq.op);
 
     rpmMessage(RPMMESS_DEBUG,
        _("%s: waitpid(%d) rc %d status %x secs %u.%03u\n"),
@@ -1112,7 +1112,9 @@ rpmpsm rpmpsmFree(rpmpsm psm)
 #else
     psm->te = NULL;
 #endif
+/*@-internalglobs@*/
     psm->ts = rpmtsFree(psm->ts);
+/*@=internalglobs@*/
 
     (void) rpmpsmUnlink(psm, msg);
 
@@ -1517,11 +1519,10 @@ psm->te->h = headerLink(fi->h);
 
            rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, ts, fi,
                        psm->cfd, NULL, &psm->failedFile);
-           if (psm->cfd->stats != NULL) {
-               FDSTAT_t stats = psm->cfd->stats;
-               (void) rpmswAdd(&ts->op_uncompress, &stats->ops[FDSTAT_READ]);
-               (void) rpmswAdd(&ts->op_digest, &stats->ops[FDSTAT_DIGEST]);
-           }
+           (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS),
+                       fdstat_op(psm->cfd, FDSTAT_READ));
+           (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
+                       fdstat_op(psm->cfd, FDSTAT_DIGEST));
            xx = fsmTeardown(fi->fsm);
 
            saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
@@ -1601,11 +1602,10 @@ psm->te->h = headerLink(fi->h);
 
            rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, psm->cfd,
                        NULL, &psm->failedFile);
-           if (psm->cfd->stats != NULL) {
-               FDSTAT_t stats = psm->cfd->stats;
-               (void) rpmswAdd(&ts->op_uncompress, &stats->ops[FDSTAT_WRITE]);
-               (void) rpmswAdd(&ts->op_digest, &stats->ops[FDSTAT_DIGEST]);
-           }
+           (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_COMPRESS),
+                       fdstat_op(psm->cfd, FDSTAT_WRITE));
+           (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
+                       fdstat_op(psm->cfd, FDSTAT_DIGEST));
            xx = fsmTeardown(fi->fsm);
 
            saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
@@ -1885,21 +1885,21 @@ assert(psm->mi == NULL);
     case PSM_RPMDB_ADD:
        if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
        if (fi->h == NULL)      break;  /* XXX can't happen */
-       (void) rpmswEnter(&ts->op_dbadd, 0);
+       (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
        if (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
            rc = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->h,
                                ts, headerCheck);
        else
            rc = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->h,
                                NULL, NULL);
-       (void) rpmswExit(&ts->op_dbadd, 0);
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
        break;
     case PSM_RPMDB_REMOVE:
        if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
-       (void) rpmswEnter(&ts->op_dbremove, 0);
+       (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
        rc = rpmdbRemove(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->record,
                                NULL, NULL);
-       (void) rpmswExit(&ts->op_dbremove, 0);
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
        break;
 
     default:
index bf0c168..b6cdea3 100644 (file)
@@ -752,7 +752,7 @@ rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
 
     if (al->list != NULL)      /* XXX always true */
     for (ret = NULL, found = 0;
-        match <= ai->index + ai->size && indexcmp(match, needle) == 0;
+        match < ai->index + ai->size && indexcmp(match, needle) == 0;
         match++)
     {
        alp = al->list + alKey2Num(al, match->pkgKey);
index e1e882f..de3ce5c 100644 (file)
@@ -543,8 +543,10 @@ rpmtsi XrpmtsiFree(/*@only@*//*@null@*/ rpmtsi tsi,
                const char * fn, unsigned int ln)
 {
     /* XXX watchout: a funky recursion segfaults here iff nrefs is wrong. */
+/*@-internalglobs@*/
     if (tsi)
        tsi->ts = rpmtsFree(tsi->ts);
+/*@=internalglobs@*/
 
 /*@-modfilesys@*/
 if (_rpmte_debug)
index c56609f..0b9eec8 100644 (file)
@@ -133,9 +133,9 @@ int rpmtsCloseDB(rpmts ts)
     int rc = 0;
 
     if (ts->rdb != NULL) {
-       (void) rpmswAdd(&ts->op_dbget, &ts->rdb->db_getops);
-       (void) rpmswAdd(&ts->op_dbput, &ts->rdb->db_putops);
-       (void) rpmswAdd(&ts->op_dbdel, &ts->rdb->db_delops);
+       (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->rdb->db_getops);
+       (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->rdb->db_putops);
+       (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->rdb->db_delops);
        rc = rpmdbClose(ts->rdb);
        ts->rdb = NULL;
     }
@@ -316,9 +316,9 @@ int rpmtsCloseSDB(rpmts ts)
     int rc = 0;
 
     if (ts->sdb != NULL) {
-       (void) rpmswAdd(&ts->op_dbget, &ts->sdb->db_getops);
-       (void) rpmswAdd(&ts->op_dbput, &ts->sdb->db_putops);
-       (void) rpmswAdd(&ts->op_dbdel, &ts->sdb->db_delops);
+       (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->sdb->db_getops);
+       (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->sdb->db_putops);
+       (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->sdb->db_delops);
        rc = rpmdbClose(ts->sdb);
        ts->sdb = NULL;
     }
@@ -636,42 +636,41 @@ void rpmtsEmpty(rpmts ts)
 /*@=nullstate@*/
 }
 
-static void rpmtsPrintStat(const char * name, struct rpmop_s * op)
+static void rpmtsPrintStat(const char * name, /*@null@*/ struct rpmop_s * op)
        /*@globals fileSystem @*/
        /*@modifies fileSystem @*/
 {
-    static unsigned uscale = (1000 * 1000);
-    static unsigned mscale = (1024 * 1024);
-    if (op->count > 0)
+    static unsigned int scale = (1000 * 1000);
+    if (op != NULL && op->count > 0)
        fprintf(stderr, "   %s %6d %6lu.%06lu MB %6lu.%06lu secs\n",
                name, op->count,
-               (unsigned long)op->bytes/mscale, (unsigned long)op->bytes%mscale,
-               op->usecs/uscale, op->usecs%uscale);
+               (unsigned long)op->bytes/scale, (unsigned long)op->bytes%scale,
+               op->usecs/scale, op->usecs%scale);
 }
 
 static void rpmtsPrintStats(rpmts ts)
-       /*@globals fileSystem @*/
-       /*@modifies fileSystem @*/
-{
-    (void) rpmswExit(&ts->op_total, 0);
-
-    rpmtsPrintStat("total:       ", &ts->op_total);
-    rpmtsPrintStat("check:       ", &ts->op_check);
-    rpmtsPrintStat("order:       ", &ts->op_order);
-    rpmtsPrintStat("fingerprint: ", &ts->op_fingerprint);
-    rpmtsPrintStat("repackage:   ", &ts->op_repackage);
-    rpmtsPrintStat("install:     ", &ts->op_install);
-    rpmtsPrintStat("erase:       ", &ts->op_erase);
-    rpmtsPrintStat("scriptlets:  ", &ts->op_scriptlets);
-    rpmtsPrintStat("compress:    ", &ts->op_compress);
-    rpmtsPrintStat("uncompress:  ", &ts->op_uncompress);
-    rpmtsPrintStat("digest:      ", &ts->op_digest);
-    rpmtsPrintStat("signature:   ", &ts->op_signature);
-    rpmtsPrintStat("dbadd:       ", &ts->op_dbadd);
-    rpmtsPrintStat("dbremove:    ", &ts->op_dbremove);
-    rpmtsPrintStat("dbget:       ", &ts->op_dbget);
-    rpmtsPrintStat("dbput:       ", &ts->op_dbput);
-    rpmtsPrintStat("dbdel:       ", &ts->op_dbdel);
+       /*@globals fileSystem, internalState @*/
+       /*@modifies fileSystem, internalState @*/
+{
+    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_TOTAL), 0);
+
+    rpmtsPrintStat("total:       ", rpmtsOp(ts, RPMTS_OP_TOTAL));
+    rpmtsPrintStat("check:       ", rpmtsOp(ts, RPMTS_OP_CHECK));
+    rpmtsPrintStat("order:       ", rpmtsOp(ts, RPMTS_OP_ORDER));
+    rpmtsPrintStat("fingerprint: ", rpmtsOp(ts, RPMTS_OP_FINGERPRINT));
+    rpmtsPrintStat("repackage:   ", rpmtsOp(ts, RPMTS_OP_REPACKAGE));
+    rpmtsPrintStat("install:     ", rpmtsOp(ts, RPMTS_OP_INSTALL));
+    rpmtsPrintStat("erase:       ", rpmtsOp(ts, RPMTS_OP_ERASE));
+    rpmtsPrintStat("scriptlets:  ", rpmtsOp(ts, RPMTS_OP_SCRIPTLETS));
+    rpmtsPrintStat("compress:    ", rpmtsOp(ts, RPMTS_OP_COMPRESS));
+    rpmtsPrintStat("uncompress:  ", rpmtsOp(ts, RPMTS_OP_UNCOMPRESS));
+    rpmtsPrintStat("digest:      ", rpmtsOp(ts, RPMTS_OP_DIGEST));
+    rpmtsPrintStat("signature:   ", rpmtsOp(ts, RPMTS_OP_SIGNATURE));
+    rpmtsPrintStat("dbadd:       ", rpmtsOp(ts, RPMTS_OP_DBADD));
+    rpmtsPrintStat("dbremove:    ", rpmtsOp(ts, RPMTS_OP_DBREMOVE));
+    rpmtsPrintStat("dbget:       ", rpmtsOp(ts, RPMTS_OP_DBGET));
+    rpmtsPrintStat("dbput:       ", rpmtsOp(ts, RPMTS_OP_DBPUT));
+    rpmtsPrintStat("dbdel:       ", rpmtsOp(ts, RPMTS_OP_DBDEL));
 }
 
 rpmts rpmtsFree(rpmts ts)
@@ -714,11 +713,11 @@ rpmts rpmtsFree(rpmts ts)
     ts->pkpktlen = 0;
     memset(ts->pksignid, 0, sizeof(ts->pksignid));
 
-    (void) rpmtsUnlink(ts, "tsCreate");
-
     if (_rpmts_stats)
        rpmtsPrintStats(ts);
 
+    (void) rpmtsUnlink(ts, "tsCreate");
+
     /*@-refcounttrans -usereleased @*/
     ts = _free(ts);
     /*@=refcounttrans =usereleased @*/
@@ -1227,6 +1226,17 @@ uint_32 rpmtsSetColor(rpmts ts, uint_32 color)
     return ocolor;
 }
 
+rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
+{
+    rpmop op = NULL;
+
+    if (ts != NULL && opx >= 0 && opx < RPMTS_OP_MAX)
+       op = ts->ops + opx;
+/*@-usereleased -compdef @*/
+    return op;
+/*@=usereleased =compdef @*/
+}
+
 int rpmtsSetNotifyCallback(rpmts ts,
                rpmCallbackFunction notify, rpmCallbackData notifyData)
 {
@@ -1272,7 +1282,8 @@ rpmts rpmtsCreate(void)
     rpmts ts;
 
     ts = xcalloc(1, sizeof(*ts));
-    (void) rpmswEnter(&ts->op_total, -1);
+    memset(&ts->ops, 0, sizeof(ts->ops));
+    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1);
     ts->goal = TSM_UNKNOWN;
     ts->filesystemCount = 0;
     ts->filesystems = NULL;
index 95ba0b8..c00609d 100644 (file)
@@ -62,6 +62,30 @@ typedef enum rpmVSFlags_e {
     RPMVSF_NODSA |             \
     RPMVSF_NORSA )
 
+/**
+ * Indices for timestamps.
+ */
+typedef        enum rpmtsOpX_e {
+    RPMTS_OP_TOTAL             =  0,
+    RPMTS_OP_CHECK             =  1,
+    RPMTS_OP_ORDER             =  2,
+    RPMTS_OP_FINGERPRINT       =  3,
+    RPMTS_OP_REPACKAGE         =  4,
+    RPMTS_OP_INSTALL           =  5,
+    RPMTS_OP_ERASE             =  6,
+    RPMTS_OP_SCRIPTLETS                =  7,
+    RPMTS_OP_COMPRESS          =  8,
+    RPMTS_OP_UNCOMPRESS                =  9,
+    RPMTS_OP_DIGEST            = 10,
+    RPMTS_OP_SIGNATURE         = 11,
+    RPMTS_OP_DBADD             = 12,
+    RPMTS_OP_DBREMOVE          = 13,
+    RPMTS_OP_DBGET             = 14,
+    RPMTS_OP_DBPUT             = 15,
+    RPMTS_OP_DBDEL             = 16,
+    RPMTS_OP_MAX               = 17
+} rpmtsOpX;
+
 #if defined(_RPMTS_INTERNAL)
 
 #include "rpmhash.h"   /* XXX hashTable */
@@ -196,23 +220,7 @@ struct rpmts_s {
     size_t pkpktlen;           /*!< Current pubkey packet length. */
     unsigned char pksignid[8]; /*!< Current pubkey fingerprint. */
 
-    struct rpmop_s op_total;
-    struct rpmop_s op_check;
-    struct rpmop_s op_order;
-    struct rpmop_s op_fingerprint;
-    struct rpmop_s op_repackage;
-    struct rpmop_s op_install;
-    struct rpmop_s op_erase;
-    struct rpmop_s op_scriptlets;
-    struct rpmop_s op_compress;
-    struct rpmop_s op_uncompress;
-    struct rpmop_s op_digest;
-    struct rpmop_s op_signature;
-    struct rpmop_s op_dbadd;
-    struct rpmop_s op_dbremove;
-    struct rpmop_s op_dbget;
-    struct rpmop_s op_dbput;
-    struct rpmop_s op_dbdel;
+    struct rpmop_s ops[RPMTS_OP_MAX];
 
 /*@null@*/
     pgpDig dig;                        /*!< Current signature/pubkey parameters. */
@@ -461,16 +469,16 @@ void rpmtsCleanDig(rpmts ts)
  * @param ts           transaction set
  */
 void rpmtsClean(rpmts ts)
-       /*@globals fileSystem @*/
-       /*@modifies ts, fileSystem @*/;
+       /*@globals fileSystem, internalState @*/
+       /*@modifies ts, fileSystem , internalState@*/;
 
 /** \ingroup rpmts
  * Re-create an empty transaction set.
  * @param ts           transaction set
  */
 void rpmtsEmpty(rpmts ts)
-       /*@globals fileSystem @*/
-       /*@modifies ts, fileSystem @*/;
+       /*@globals fileSystem, internalState @*/
+       /*@modifies ts, fileSystem, internalState @*/;
 
 /** \ingroup rpmts
  * Destroy transaction set, closing the database as well.
@@ -479,8 +487,8 @@ void rpmtsEmpty(rpmts ts)
  */
 /*@null@*/
 rpmts rpmtsFree(/*@killref@*/ /*@only@*//*@null@*/ rpmts ts)
-       /*@globals fileSystem @*/
-       /*@modifies ts, fileSystem @*/;
+       /*@globals fileSystem, internalState @*/
+       /*@modifies ts, fileSystem, internalState @*/;
 
 /** \ingroup rpmts
  * Get verify signatures flag(s).
@@ -792,6 +800,16 @@ Spec rpmtsSetSpec(rpmts ts, /*@null@*/ Spec spec)
 rpmte rpmtsRelocateElement(rpmts ts)
        /*@*/;
 
+/** \ingroup rpmts
+ * Set current relocate transaction element.
+ * @param ts           transaction set
+ * @param relocateElement new relocate transaction element
+ * @return             previous relocate transaction element
+ */
+/*@null@*/
+rpmte rpmtsSetRelocateElement(rpmts ts, /*@null@*/ rpmte relocateElement)
+       /*@modifies ts @*/;
+
 /**
  * Retrieve color bits of transaction set.
  * @param ts           transaction set
@@ -809,15 +827,15 @@ uint_32 rpmtsColor(rpmts ts)
 uint_32 rpmtsSetColor(rpmts ts, uint_32 color)
        /*@modifies ts @*/;
 
-/** \ingroup rpmts
- * Set current relocate transaction element.
+/**
+ * Retrieve operation timestamp from a transaction set.
  * @param ts           transaction set
- * @param relocateElement new relocate transaction element
- * @return             previous relocate transaction element
+ * @param opx          operation timestamp index
+ * @return             pointer to operation timestamp.
  */
 /*@null@*/
-rpmte rpmtsSetRelocateElement(rpmts ts, /*@null@*/ rpmte relocateElement)
-       /*@modifies ts @*/;
+rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
+       /*@*/;
 
 /** \ingroup rpmts
  * Set transaction notify callback function and argument.
@@ -888,8 +906,8 @@ int rpmtsAddEraseElement(rpmts ts, Header h, int dboffset)
 int rpmtsGetKeys(rpmts ts,
                /*@null@*/ /*@out@*/ fnpyKey ** ep,
                /*@null@*/ /*@out@*/ int * nep)
-       /*@globals fileSystem @*/
-       /*@modifies ts, ep, nep, fileSystem @*/;
+       /*@globals fileSystem, internalState @*/
+       /*@modifies ts, ep, nep, fileSystem, internalState @*/;
 
 /**
  * Return (malloc'd) header name-version-release string.
index 5fa6690..eff62dd 100644 (file)
@@ -9,7 +9,6 @@
 #include <rpmmacro.h>  /* XXX for rpmGetPath() */
 #include "rpmdb.h"
 
-#define        _RPMTS_INTERNAL
 #include "rpmts.h"
 
 #include "misc.h"      /* XXX for dosetenv() and makeTempFile() */
@@ -1003,7 +1002,8 @@ exit:
 static rpmRC
 verifyMD5Signature(const rpmts ts, /*@out@*/ char * t,
                /*@null@*/ DIGEST_CTX md5ctx)
-       /*@modifies *t @*/
+       /*@globals internalState @*/
+       /*@modifies *t, internalState @*/
 {
     const void * sig = rpmtsSig(ts);
     int_32 siglen = rpmtsSiglen(ts);
@@ -1021,10 +1021,10 @@ verifyMD5Signature(const rpmts ts, /*@out@*/ char * t,
        goto exit;
     }
 
-    (void) rpmswEnter(&ts->op_digest, 0);
+    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
     (void) rpmDigestFinal(rpmDigestDup(md5ctx),
                (void **)&md5sum, &md5len, 0);
-    (void) rpmswExit(&ts->op_digest, 0);
+    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
 
     if (md5len != siglen || memcmp(md5sum, sig, md5len)) {
        res = RPMRC_FAIL;
@@ -1060,7 +1060,8 @@ exit:
 static rpmRC
 verifySHA1Signature(const rpmts ts, /*@out@*/ char * t,
                /*@null@*/ DIGEST_CTX sha1ctx)
-       /*@modifies *t @*/
+       /*@globals internalState @*/
+       /*@modifies *t, internalState @*/
 {
     const void * sig = rpmtsSig(ts);
 #ifdef NOTYET
@@ -1079,10 +1080,10 @@ verifySHA1Signature(const rpmts ts, /*@out@*/ char * t,
        goto exit;
     }
 
-    (void) rpmswEnter(&ts->op_digest, 0);
+    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
     (void) rpmDigestFinal(rpmDigestDup(sha1ctx),
                (void **)&SHA1, NULL, 1);
-    (void) rpmswExit(&ts->op_digest, 0);
+    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
 
     if (SHA1 == NULL || strlen(SHA1) != strlen(sig) || strcmp(SHA1, sig)) {
        res = RPMRC_FAIL;
@@ -1164,7 +1165,7 @@ verifyPGPSignature(rpmts ts, /*@out@*/ char * t,
        goto exit;
     }
 
-    (void) rpmswEnter(&ts->op_digest, 0);
+    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
     {  DIGEST_CTX ctx = rpmDigestDup(md5ctx);
        byte signhash16[2];
        const char * s;
@@ -1185,7 +1186,7 @@ verifyPGPSignature(rpmts ts, /*@out@*/ char * t,
 #endif
 
        xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 1);
-       (void) rpmswExit(&ts->op_digest, sigp->hashlen);
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), sigp->hashlen);
 
        /* Compare leading 16 bits of digest for quick check. */
        s = dig->md5;
@@ -1224,12 +1225,12 @@ verifyPGPSignature(rpmts ts, /*@out@*/ char * t,
     if (res != RPMRC_OK)
        goto exit;
 
-    (void) rpmswEnter(&ts->op_signature, 0);
+    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
     if (rsavrfy(&dig->rsa_pk, &dig->rsahm, &dig->c))
        res = RPMRC_OK;
     else
        res = RPMRC_FAIL;
-    (void) rpmswExit(&ts->op_signature, 0);
+    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
 
 exit:
     t = stpcpy(t, rpmSigString(res));
@@ -1286,11 +1287,10 @@ verifyGPGSignature(rpmts ts, /*@out@*/ char * t,
        goto exit;
     }
 
-    (void) rpmswEnter(&ts->op_digest, 0);
+    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
     {  DIGEST_CTX ctx = rpmDigestDup(sha1ctx);
        byte signhash16[2];
 
-       (void) rpmswEnter(&ts->op_digest, 0);
        if (sigp->hash != NULL)
            xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
 
@@ -1306,7 +1306,7 @@ verifyGPGSignature(rpmts ts, /*@out@*/ char * t,
        }
 #endif
        xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 1);
-       (void) rpmswExit(&ts->op_digest, sigp->hashlen);
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), sigp->hashlen);
 
        mp32nzero(&dig->hm);    mp32nsethex(&dig->hm, dig->sha1);
 
@@ -1324,13 +1324,13 @@ verifyGPGSignature(rpmts ts, /*@out@*/ char * t,
     if (res != RPMRC_OK)
        goto exit;
 
-    (void) rpmswEnter(&ts->op_signature, 0);
+    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
     if (dsavrfy(&dig->p, &dig->q, &dig->g,
                &dig->hm, &dig->y, &dig->r, &dig->s))
        res = RPMRC_OK;
     else
        res = RPMRC_FAIL;
-    (void) rpmswExit(&ts->op_signature, 0);
+    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
 
 exit:
     t = stpcpy(t, rpmSigString(res));
index a93757e..d019de4 100644 (file)
@@ -1209,7 +1209,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount)
            continue;   /* XXX can't happen */
        fc = rpmfiFC(fi);
 
-       (void) rpmswEnter(&ts->op_fingerprint, 0);
+       (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
        fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps);
        /*@-branchstate@*/
        fi = rpmfiInit(fi, 0);
@@ -1222,7 +1222,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount)
            /*@=dependenttrans@*/
        }
        /*@=branchstate@*/
-       (void) rpmswExit(&ts->op_fingerprint, fc);
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
 
     }
     pi = rpmtsiFree(pi);
@@ -1252,7 +1252,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
 
        if (fc == 0) continue;
 
-       (void) rpmswEnter(&ts->op_fingerprint, 0);
+       (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
        /* Extract file info for all files in this package from the database. */
        matches = xcalloc(fc, sizeof(*matches));
        if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc)) {
@@ -1352,7 +1352,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
        case TR_REMOVED:
            /*@switchbreak@*/ break;
        }
-       (void) rpmswExit(&ts->op_fingerprint, fc);
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
     }
     pi = rpmtsiFree(pi);
     ps = rpmpsFree(ps);
@@ -1425,7 +1425,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
                        numRemoved, NULL, ts->notifyData));
                progress++;
 
-               (void) rpmswEnter(&ts->op_repackage, 0);
+               (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
 
        /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
                fi->mapflags |= CPIO_MAP_ABSOLUTE;
@@ -1438,7 +1438,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
                fi->mapflags &= ~CPIO_MAP_ADDDOT;
                fi->mapflags &= ~CPIO_ALL_HARDLINKS;
 
-               (void) rpmswExit(&ts->op_repackage, 0);
+               (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
 
                /*@switchbreak@*/ break;
            }
@@ -1473,7 +1473,7 @@ assert(psm != NULL);
 
        switch (rpmteType(p)) {
        case TR_ADDED:
-           (void) rpmswEnter(&ts->op_install, 0);
+           (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
 
            pkgKey = rpmteAddedKey(p);
 
@@ -1570,12 +1570,12 @@ assert(psm != NULL);
 
            p->h = headerFree(p->h);
 
-           (void) rpmswExit(&ts->op_install, 0);
+           (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
 
            /*@switchbreak@*/ break;
 
        case TR_REMOVED:
-           (void) rpmswEnter(&ts->op_erase, 0);
+           (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
 
            rpmMessage(RPMMESS_DEBUG, "========== --- %s\n", rpmteNEVR(p));
            /*
@@ -1587,7 +1587,7 @@ assert(psm != NULL);
                    ourrc++;
            }
 
-           (void) rpmswExit(&ts->op_erase, 0);
+           (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
 
            /*@switchbreak@*/ break;
        }
index ebe3a31..946d7d2 100644 (file)
@@ -1536,7 +1536,7 @@ static rpmRC dbiFindByLabel(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
  */
 static int miFreeHeader(rpmdbMatchIterator mi, dbiIndex dbi)
        /*@globals fileSystem, internalState @*/
-       /*@modifies mi, fileSystem, internalState @*/
+       /*@modifies mi, dbi, fileSystem, internalState @*/
 {
     int rc = 0;
 
@@ -2279,8 +2279,8 @@ static void rpmdbSortIterator(/*@null@*/ rpmdbMatchIterator mi)
 
 /*@-bounds@*/ /* LCL: segfault */
 static int rpmdbGrowIterator(/*@null@*/ rpmdbMatchIterator mi, int fpNum)
-       /*@globals rpmGlobalMacroContext, fileSystem @*/
-       /*@modifies mi, rpmGlobalMacroContext, fileSystem @*/
+       /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
+       /*@modifies mi, rpmGlobalMacroContext, fileSystem, internalState @*/
 {
     DBC * dbcursor;
     DBT * key;
index 2affb46..afb4609 100644 (file)
@@ -559,8 +559,8 @@ int dbiCdup(dbiIndex dbi, DBC * dbcursor, /*@out@*/ DBC ** dbcp,
 /*@unused@*/ static inline
 int dbiDel(dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key, DBT * data,
                unsigned int flags)
-       /*@globals fileSystem @*/
-       /*@modifies *dbcursor, fileSystem @*/
+       /*@globals fileSystem, internalState @*/
+       /*@modifies dbi, *dbcursor, fileSystem, internalState @*/
 {
     int rc;
     assert(key->data != NULL && key->size > 0);
@@ -582,8 +582,8 @@ int dbiDel(dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key, DBT * data,
 /*@unused@*/ static inline
 int dbiGet(dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key, DBT * data,
                unsigned int flags)
-       /*@globals fileSystem @*/
-       /*@modifies *dbcursor, *key, *data, fileSystem @*/
+       /*@globals fileSystem, internalState @*/
+       /*@modifies dbi, *dbcursor, *key, *data, fileSystem, internalState @*/
 {
     int rc;
     assert((flags == DB_NEXT) || (key->data != NULL && key->size > 0));
@@ -606,8 +606,8 @@ int dbiGet(dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key, DBT * data,
 /*@unused@*/ static inline
 int dbiPget(dbiIndex dbi, /*@null@*/ DBC * dbcursor,
                DBT * key, DBT * pkey, DBT * data, unsigned int flags)
-       /*@globals fileSystem @*/
-       /*@modifies *dbcursor, *key, *pkey, *data, fileSystem @*/
+       /*@globals fileSystem, internalState @*/
+       /*@modifies dbi, *dbcursor, *key, *pkey, *data, fileSystem, internalState @*/
 {
     int rc;
     assert((flags == DB_NEXT) || (key->data != NULL && key->size > 0));
@@ -629,8 +629,8 @@ int dbiPget(dbiIndex dbi, /*@null@*/ DBC * dbcursor,
 /*@unused@*/ static inline
 int dbiPut(dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key, DBT * data,
                unsigned int flags)
-       /*@globals fileSystem @*/
-       /*@modifies *dbcursor, *key, fileSystem @*/
+       /*@globals fileSystem, internalState @*/
+       /*@modifies dbi, *dbcursor, *key, fileSystem, internalState @*/
 {
     int rc;
     assert(key->data != NULL && key->size > 0 && data->data != NULL && data->size > 0);
@@ -928,8 +928,8 @@ int rpmdbOpenAll (/*@null@*/ rpmdb db)
  * @return             number of instances
  */
 int rpmdbCountPackages(/*@null@*/ rpmdb db, const char * name)
-       /*@globals rpmGlobalMacroContext, fileSystem @*/
-       /*@modifies db, rpmGlobalMacroContext, fileSystem @*/;
+       /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
+       /*@modifies db, rpmGlobalMacroContext, fileSystem, internalState @*/;
 
 /** \ingroup rpmdb
  * Return header join key for current position of rpm database iterator.
index 2be3ceb..505c6da 100644 (file)
@@ -104,14 +104,14 @@ typedef struct _FDSTACK_s {
 /** \ingroup rpmio
  * Identify per-desciptor I/O operation statistics.
  */
-enum FDSTAT_e {
+typedef enum fdOpX_e {
     FDSTAT_READ                = 0,    /*!< Read statistics index. */
     FDSTAT_WRITE       = 1,    /*!< Write statistics index. */
     FDSTAT_SEEK                = 2,    /*!< Seek statistics index. */
     FDSTAT_CLOSE       = 3,    /*!< Close statistics index */
     FDSTAT_DIGEST      = 4,    /*!< Digest statistics index. */
     FDSTAT_MAX         = 5
-};
+} fdOpX;
 
 /** \ingroup rpmio
  * Cumulative statistics for a descriptor.
@@ -346,7 +346,8 @@ void fdPush(FD_t fd, FDIO_t io, void * fp, int fdno)
 
 /** \ingroup rpmio
  */
-/*@unused@*/ static inline void fdPop(FD_t fd)
+/*@unused@*/ static inline
+void fdPop(FD_t fd)
        /*@modifies fd @*/
 {
     FDSANE(fd);
@@ -359,16 +360,29 @@ void fdPush(FD_t fd, FDIO_t io, void * fp, int fdno)
 
 /** \ingroup rpmio
  */
+/*@unused@*/ static inline /*@null@*/
+rpmop fdstat_op(/*@null@*/ FD_t fd, fdOpX opx)
+       /*@*/
+{
+    rpmop op = NULL;
+
+/*@-boundsread@*/
+    if (fd != NULL && fd->stats != NULL && opx >= 0 && opx < FDSTAT_MAX)
+        op = fd->stats->ops + opx;
+/*@=boundsread@*/
+    return op;
+}
+
+/** \ingroup rpmio
+ */
 /*@unused@*/ static inline
 void fdstat_enter(/*@null@*/ FD_t fd, int opx)
        /*@globals internalState @*/
-       /*@modifies fd, internalState @*/
+       /*@modifies internalState @*/
 {
     if (fd == NULL) return;
-/*@-boundswrite@*/
     if (fd->stats != NULL)
-       (void) rpmswEnter(&fd->stats->ops[opx], 0);
-/*@=boundswrite@*/
+       (void) rpmswEnter(fdstat_op(fd, opx), 0);
 }
 
 /** \ingroup rpmio
@@ -383,10 +397,8 @@ void fdstat_exit(/*@null@*/ FD_t fd, int opx, ssize_t rc)
        fd->syserrno = errno;
     else if (rc > 0 && fd->bytesRemain > 0)
        fd->bytesRemain -= rc;
-/*@-boundswrite@*/
     if (fd->stats != NULL)
-       (void) rpmswExit(&fd->stats->ops[opx], rc);
-/*@=boundswrite@*/
+       (void) rpmswExit(fdstat_op(fd, opx), rc);
 }
 
 /** \ingroup rpmio
@@ -487,7 +499,8 @@ FD_t c2f(/*@null@*/ void * cookie)
  */
 /*@unused@*/ static inline
 void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int flags)
-       /*@modifies fd @*/
+       /*@globals internalState @*/
+       /*@modifies fd, internalState @*/
 {
     FDDIGEST_t fddig = fd->digests + fd->ndigests;
     if (fddig != (fd->digests + FDDIGEST_MAX)) {
@@ -504,7 +517,8 @@ void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int flags)
  */
 /*@unused@*/ static inline
 void fdUpdateDigests(FD_t fd, const unsigned char * buf, ssize_t buflen)
-       /*@modifies fd @*/
+       /*@globals internalState @*/
+       /*@modifies fd, internalState @*/
 {
     int i;
 
@@ -526,7 +540,8 @@ void fdFiniDigest(FD_t fd, pgpHashAlgo hashalgo,
                /*@null@*/ /*@out@*/ void ** datap,
                /*@null@*/ /*@out@*/ size_t * lenp,
                int asAscii)
-       /*@modifies fd, *datap, *lenp @*/
+       /*@globals internalState @*/
+       /*@modifies fd, *datap, *lenp, internalState @*/
 {
     int imax = -1;
     int i;
index de21d88..9f3be35 100644 (file)
@@ -903,6 +903,7 @@ static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall,
        /* XXX FIXME: realloc ftpBuf if < ~128 chars remain */
        if ((ftpBufAlloced - bufLength) < (1024+80)) {
            ftpBufAlloced <<= 2;
+           assert(ftpBufAlloced < (8*1024*1024));
            ftpBuf = xrealloc(ftpBuf, ftpBufAlloced);
        }
        s = se = ftpBuf + bufLength;
index b51a3dc..f8b2fc9 100644 (file)
@@ -179,7 +179,6 @@ static rpmtime_t rpmswCalibrate(void)
 /*@=type@*/
 #endif
 
-/*@-incondefs@*/
 rpmtime_t rpmswInit(void)
        /*@globals rpmsw_cycles, rpmsw_initialized, rpmsw_overhead,
                rpmsw_type @*/
@@ -228,6 +227,8 @@ rpmtime_t rpmswInit(void)
 
        /* Compute cycles/usec */
        rpmsw_cycles = sum_cycles/sum_usecs;
+#else
+       rpmsw_type = 0;
 #endif
 
        /* Calculate timing overhead in usecs. */
@@ -242,11 +243,13 @@ rpmtime_t rpmswInit(void)
 
     return rpmsw_overhead;
 }
-/*@=incondefs@*/
 
 /*@-mods@*/
 int rpmswEnter(rpmop op, ssize_t rc)
 {
+    if (op == NULL)
+       return 0;
+
     op->count++;
     if (rc < 0) {
        op->bytes = 0;
@@ -262,6 +265,9 @@ rpmtime_t rpmswExit(rpmop op, ssize_t rc)
 {
     struct rpmsw_s end;
 
+    if (op == NULL)
+       return 0;
+
 /*@-uniondef@*/
     op->usecs += rpmswDiff(rpmswNow(&end), &op->begin);
 /*@=uniondef@*/
@@ -273,22 +279,26 @@ rpmtime_t rpmswExit(rpmop op, ssize_t rc)
 
 rpmtime_t rpmswAdd(rpmop to, rpmop from)
 {
+    rpmtime_t usecs = 0;
     if (to != NULL && from != NULL) {
        to->count += from->count;
        to->bytes += from->bytes;
        to->usecs += from->usecs;
+       usecs = to->usecs;
     }
-    return to->usecs;
+    return usecs;
 }
 
 rpmtime_t rpmswSub(rpmop to, rpmop from)
 {
+    rpmtime_t usecs = 0;
     if (to != NULL && from != NULL) {
        to->count -= from->count;
        to->bytes -= from->bytes;
        to->usecs -= from->usecs;
+       usecs = to->usecs;
     }
-    return to->usecs;
+    return usecs;
 }
 
 /*@=mods@*/
index 8bcedf2..3cae711 100644 (file)
@@ -77,7 +77,7 @@ rpmtime_t rpmswInit(void)
  * @param rc                   -1 clears usec counter
  * @return                     0 always
  */
-int rpmswEnter(rpmop op, ssize_t rc)
+int rpmswEnter(/*@null@*/ rpmop op, ssize_t rc)
        /*@globals internalState @*/
        /*@modifies *op, internalState @*/;
 
@@ -87,7 +87,7 @@ int rpmswEnter(rpmop op, ssize_t rc)
  * @param rc                   per-operation data (e.g. bytes transferred)
  * @return                     cumulative usecs for operation
  */
-rpmtime_t rpmswExit(rpmop op, ssize_t rc)
+rpmtime_t rpmswExit(/*@null@*/ rpmop op, ssize_t rc)
        /*@globals internalState @*/
        /*@modifies op, internalState @*/;
 
@@ -97,7 +97,7 @@ rpmtime_t rpmswExit(rpmop op, ssize_t rc)
  * @param from                 operation statistics
  * @return                     cumulative usecs for operation
  */
-rpmtime_t rpmswAdd(rpmop to, rpmop from)
+rpmtime_t rpmswAdd(/*@null@*/ rpmop to, /*@null@*/ rpmop from)
        /*@modifies to @*/;
 
 /** \ingroup rpmio