diff --git a/CHANGES b/CHANGES index eb1c2eb..ac54251 100644 --- a/CHANGES +++ b/CHANGES @@ -65,6 +65,12 @@ - *really* dump signature header immutable region. - fix: don't overflow result buffer if gpg/pgp gives copious output. - fix: make sure that .rpmsave files are created (#57078). + - fix: look for "/path" in Providename as well as Basenames (#59665). + - fix: avoid /dev/log installation more carefully (#62012). + - fix: don't compile beecrypt java bindings (#61992). + - solaris: save main() envp in global environ for use with gpg. + - don't add empty md5 strings to Filemd5's index. + - create Filemd5 index with binary, not ascii, keys. 4.0.2 -> 4.0.3: - update per-interpreter dependency scripts, add sql/tcl (#20295). diff --git a/lib/fsm.c b/lib/fsm.c index 5b0f622..9569a0f 100644 --- a/lib/fsm.c +++ b/lib/fsm.c @@ -1201,6 +1201,12 @@ static int fsmStat(FSM_t fsm) } #endif +#define IS_DEV_LOG(_x) \ + ((_x) != NULL && strlen(_x) >= (sizeof("/dev/log")-1) && \ + !strncmp((_x), "/dev/log", sizeof("/dev/log")-1) && \ + ((_x)[sizeof("/dev/log")-1] == '\0' || \ + (_x)[sizeof("/dev/log")-1] == ';')) + /*@-compmempass@*/ int fsmStage(FSM_t fsm, fileStage stage) { @@ -1602,7 +1608,7 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break; rc = fsmStage(fsm, FSM_MKNOD); } else { /* XXX Special case /dev/log, which shouldn't be packaged anyways */ - if (strncmp(fsm->path, "/dev/log", sizeof("/dev/log")-1)) + if (!IS_DEV_LOG(fsm->path)) rc = CPIOERR_UNKNOWN_FILETYPE; } if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) { @@ -1723,9 +1729,7 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break; } /* XXX Special case /dev/log, which shouldn't be packaged anyways */ - if (!S_ISSOCK(st->st_mode) - && strncmp(fsm->path, "/dev/log", sizeof("/dev/log")-1)) - { + if (!S_ISSOCK(st->st_mode) && !IS_DEV_LOG(fsm->path)) { /* Rename temporary to final file name. */ if (!S_ISDIR(st->st_mode) && (fsm->subdir || fsm->suffix || fsm->nsuffix)) diff --git a/lib/query.c b/lib/query.c index 4d7dae1..381065b 100644 --- a/lib/query.c +++ b/lib/query.c @@ -766,10 +766,11 @@ restart: return 1; } + md5[0] = '\0'; for (i = 0, t = md5, s = arg; i < 16; i++, t++, s += 2) *t = (nibble(s[0]) << 4) | nibble(s[1]); - mi = rpmdbInitIterator(rpmdb, RPMTAG_SIGMD5, md5, 16); + mi = rpmdbInitIterator(rpmdb, RPMTAG_SIGMD5, md5, sizeof(md5)); if (mi == NULL) { rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"), "pkgid", arg); @@ -798,6 +799,9 @@ restart: break; case RPMQV_FILEID: + { unsigned char md5[16]; + unsigned char * t; + for (i = 0, s = arg; *s && isxdigit(*s); s++, i++) {}; if (i != 32) { @@ -805,7 +809,11 @@ restart: return 1; } - mi = rpmdbInitIterator(rpmdb, RPMTAG_FILEMD5S, arg, 0); + md5[0] = '\0'; + for (i = 0, t = md5, s = arg; i < 16; i++, t++, s += 2) + *t = (nibble(s[0]) << 4) | nibble(s[1]); + + mi = rpmdbInitIterator(rpmdb, RPMTAG_FILEMD5S, md5, sizeof(md5)); if (mi == NULL) { rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"), "fileid", arg); @@ -813,7 +821,7 @@ restart: } else { retcode = showMatches(qva, mi, showPackage); } - break; + } break; case RPMQV_TID: { int mybase = 10; @@ -855,14 +863,14 @@ restart: break; case RPMQV_WHATPROVIDES: - mi = rpmdbInitIterator(rpmdb, RPMTAG_PROVIDENAME, arg, 0); - if (mi == NULL) { - if (arg[0] != '/') + mi = rpmdbInitIterator(rpmdb, RPMTAG_PROVIDENAME, arg, 0); + if (mi == NULL) { + if (arg[0] != '/') rpmError(RPMERR_QUERYINFO, _("no package provides %s\n"), arg); - retcode = 1; - } else { - retcode = showMatches(qva, mi, showPackage); - } + retcode = 1; + } else { + retcode = showMatches(qva, mi, showPackage); + } if (arg[0] != '/') break; /*@fallthrough@*/ diff --git a/rpmdb/rpmdb.c b/rpmdb/rpmdb.c index c39cc01..af63dd2 100644 --- a/rpmdb/rpmdb.c +++ b/rpmdb/rpmdb.c @@ -62,6 +62,38 @@ static int _db_filter_dups = 0; /*@unchecked@*/ int dbiTagsMax = 0; +/** + * Convert hex to binary nibble. + * @param c hex character + * @return binary nibble + */ +static inline unsigned char nibble(char c) + /*@*/ +{ + if (c >= '0' && c <= '9') + return (c - '0'); + if (c >= 'A' && c <= 'F') + return (c - 'A') + 10; + if (c >= 'a' && c <= 'f') + return (c - 'a') + 10; + return 0; +} + +/** + * Check key for printable characters. + * @param ptr key value pointer + * @param len key value length + * @return 1 if only ASCII, 0 otherwise. + */ +static int printable(const void * ptr, size_t len) /*@*/ +{ + const char * s = ptr; + int i; + for (i = 0; i < len; i++, s++) + if (!(*s >= ' ' && *s <= '~')) return 0; + return 1; +} + /** * Return dbi index used for rpm tag. * @param rpmtag rpm header tag @@ -199,15 +231,6 @@ fprintf(stderr, "--- RMW %s\n", tagName(dbi->dbi_rpmtag)); return (*dbi->dbi_vec->cclose) (dbi, dbcursor, flags); } -static int printable(const void * ptr, size_t len) /*@*/ -{ - const char * s = ptr; - int i; - for (i = 0; i < len; i++, s++) - if (!(*s >= ' ' && *s <= '~')) return 0; - return 1; -} - INLINE int dbiDel(dbiIndex dbi, DBC * dbcursor, const void * keyp, size_t keylen, unsigned int flags) { @@ -247,13 +270,24 @@ if (_debug < 0 || dbi->dbi_debug) { char keyval[64]; keyval[0] = '\0'; if (keypp && *keypp && keylenp) { - if (*keylenp <= sizeof(int) && !printable(*keypp, *keylenp)) { + if (printable(*keypp, *keylenp)) { + kvp = *keypp; + } else if (*keylenp <= sizeof(int)) { int keyint = 0; memcpy(&keyint, *keypp, sizeof(keyint)); sprintf(keyval, "#%d", keyint); kvp = keyval; } else { - kvp = *keypp; + static const char hex[] = "0123456789abcdef"; + const unsigned char * s = *keypp; + char * t = keyval; + int i; + for (i = 0; i < *keylenp && t < (keyval+sizeof(keyval)-2); i++) { + *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ]; + *t++ = hex[ (unsigned)((*s++ ) & 0x0f) ]; + } + *t = '\0'; + kvp = keyval; } } else kvp = keyval; @@ -288,13 +322,24 @@ if (_debug < 0 || dbi->dbi_debug) { char keyval[64]; keyval[0] = '\0'; if (keyp) { - if (keylen == sizeof(int) && !printable(keyp, keylen)) { + if (printable(keyp, keylen)) { + kvp = keyp; + } else if (keylen <= sizeof(int)) { int keyint = 0; memcpy(&keyint, keyp, sizeof(keyint)); sprintf(keyval, "#%d", keyint); kvp = keyval; } else { - kvp = keyp; + static const char hex[] = "0123456789abcdef"; + const unsigned char * s = keyp; + char * t = keyval; + int i; + for (i = 0; i < keylen && t < (keyval+sizeof(keyval)-2); i++) { + *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ]; + *t++ = hex[ (unsigned)((*s++ ) & 0x0f) ]; + } + *t = '\0'; + kvp = keyval; } } else kvp = keyval; @@ -2405,7 +2450,7 @@ int rpmdbRemove(rpmdb db, /*@unused@*/ int rid, unsigned int hdrNum) (void) blockSignals(db, &signalMask); - /*@-nullpass -nullptrarith -nullderef @*/ + /*@-nullpass -nullptrarith -nullderef @*/ /* FIX: rpmvals heartburn */ { int dbix; dbiIndexItem rec = dbiIndexNewItem(hdrNum, 0); @@ -2419,7 +2464,7 @@ int rpmdbRemove(rpmdb db, /*@unused@*/ int rid, unsigned int hdrNum) int rpmcnt = 0; int rpmtag; int xx; - int i; + int i, j; dbi = NULL; rpmtag = dbiTags[dbix]; @@ -2468,6 +2513,17 @@ int rpmdbRemove(rpmdb db, /*@unused@*/ int rid, unsigned int hdrNum) const void * valp; size_t vallen; int stringvalued; + unsigned char bin[32]; + + switch (dbi->dbi_rpmtag) { + case RPMTAG_FILEMD5S: + /* Filter out empty MD5 strings. */ + if (!(rpmvals[i] && *rpmvals[i] != '\0')) + /*@innercontinue@*/ continue; + /*@switchbreak@*/ break; + default: + /*@switchbreak@*/ break; + } /* Identify value pointer and length. */ stringvalued = 0; @@ -2495,9 +2551,41 @@ int rpmdbRemove(rpmdb db, /*@unused@*/ int rid, unsigned int hdrNum) rpmcnt = 1; /* XXX break out of loop. */ /*@fallthrough@*/ case RPM_STRING_ARRAY_TYPE: + /* Convert from hex to binary. */ + if (dbi->dbi_rpmtag == RPMTAG_FILEMD5S) { + const char * s; + unsigned char * t; + + s = rpmvals[i]; + t = bin; + for (j = 0; j < 16; j++, t++, s += 2) + *t = (nibble(s[0]) << 4) | nibble(s[1]); + valp = bin; + vallen = 16; + /*@switchbreak@*/ break; + } +#ifdef NOTYET + /* Extract the pubkey id from the base64 blob. */ + if (dbi->dbi_rpmtag == RPMTAG_PUBKEYS) { + pgpDig dig = pgpNewDig(); + const byte * pkt; + ssize_t pktlen; + + if (b64decode(rpmvals[i], (void **)&pkt, &pktlen)) + /*@innercontinue@*/ continue; + (void) pgpPrtPkts(pkt, pktlen, dig, 0); + memcpy(bin, dig->pubkey.signid, 8); + pkt = _free(pkt); + dig = _free(dig); + valp = bin; + vallen = 8; + /*@switchbreak@*/ break; + } +#endif + /*@fallthrough@*/ default: - vallen = strlen(rpmvals[i]); valp = rpmvals[i]; + vallen = strlen(rpmvals[i]); stringvalued = 1; /*@switchbreak@*/ break; } @@ -2514,6 +2602,7 @@ int rpmdbRemove(rpmdb db, /*@unused@*/ int rid, unsigned int hdrNum) } printed++; } + /* * This is almost right, but, if there are duplicate tag * values, there will be duplicate attempts to remove @@ -2773,17 +2862,27 @@ int rpmdbAdd(rpmdb db, int iid, Header h) const void * valp; size_t vallen; int stringvalued; + unsigned char bin[32]; /* * Include the tagNum in all indices. rpm-3.0.4 and earlier * included the tagNum only for files. */ + rec->tagNum = i; switch (dbi->dbi_rpmtag) { +#ifdef NOTYET + case RPMTAG_PUBKEYS: + /*@switchbreak@*/ break; +#endif + case RPMTAG_FILEMD5S: + /* Filter out empty MD5 strings. */ + if (!(rpmvals[i] && *rpmvals[i] != '\0')) + /*@innercontinue@*/ continue; + /*@switchbreak@*/ break; case RPMTAG_REQUIRENAME: /* Filter out install prerequisites. */ if (requireFlags && isInstallPreReq(requireFlags[i])) /*@innercontinue@*/ continue; - rec->tagNum = i; /*@switchbreak@*/ break; case RPMTAG_TRIGGERNAME: if (i) { /* don't add duplicates */ @@ -2794,10 +2893,8 @@ int rpmdbAdd(rpmdb db, int iid, Header h) if (j < i) /*@innercontinue@*/ continue; } - rec->tagNum = i; /*@switchbreak@*/ break; default: - rec->tagNum = i; /*@switchbreak@*/ break; } @@ -2827,6 +2924,38 @@ int rpmdbAdd(rpmdb db, int iid, Header h) rpmcnt = 1; /* XXX break out of loop. */ /*@fallthrough@*/ case RPM_STRING_ARRAY_TYPE: + /* Convert from hex to binary. */ + if (dbi->dbi_rpmtag == RPMTAG_FILEMD5S) { + const char * s; + unsigned char * t; + + s = rpmvals[i]; + t = bin; + for (j = 0; j < 16; j++, t++, s += 2) + *t = (nibble(s[0]) << 4) | nibble(s[1]); + valp = bin; + vallen = 16; + /*@switchbreak@*/ break; + } +#ifdef NOTYET + /* Extract the pubkey id from the base64 blob. */ + if (dbi->dbi_rpmtag == RPMTAG_PUBKEYS) { + pgpDig dig = pgpNewDig(); + const byte * pkt; + ssize_t pktlen; + + if (b64decode(rpmvals[i], (void **)&pkt, &pktlen)) + /*@innercontinue@*/ continue; + (void) pgpPrtPkts(pkt, pktlen, dig, 0); + memcpy(bin, dig->pubkey.signid, 8); + pkt = _free(pkt); + dig = _free(dig); + valp = bin; + vallen = 8; + /*@switchbreak@*/ break; + } +#endif + /*@fallthrough@*/ default: valp = rpmvals[i]; vallen = strlen(rpmvals[i]);