--- rpmio/rpmpgp.c.orig	2014-02-05 13:04:02.000000000 +0000
+++ rpmio/rpmpgp.c	2022-09-08 14:51:32.540386570 +0000
@@ -284,6 +284,7 @@ int pgpValTok(pgpValTbl vs, const char *
 /** \ingroup rpmpgp
  * Decode length from 1, 2, or 5 octet body length encoding, used in
  * new format packet headers and V4 signature subpackets.
+ * Partial body lengths are (intentionally) not supported.
  * @param s		pointer to length encoding buffer
  * @param slen		buffer size
  * @retval *lenp	decoded length
@@ -303,14 +304,17 @@ size_t pgpLen(const uint8_t *s, size_t s
     if (*s < 192) {
 	lenlen = 1;
 	dlen = *s;
-    } else if (*s < 255 && slen > 2) {
+    } else if (*s < 224 && slen > 2) {
 	lenlen = 2;
 	dlen = (((s[0]) - 192) << 8) + s[1] + 192;
-    } else if (slen > 5) {
+    } else if (*s == 255 && slen > 5) {
 	lenlen = 5;
 	dlen = pgpGrab(s+1, 4);
     }
 
+    if (slen - lenlen < dlen)
+	lenlen = 0;
+
     if (lenlen)
 	*lenp = dlen;
 
@@ -388,9 +392,11 @@ static int pgpPrtSubType(const uint8_t *
 			 pgpDigParams _digp)
 {
     const uint8_t *p = h;
-    size_t plen, i;
+    size_t plen = 0, i;
+    int rc = 0;
 
-    while (hlen > 0) {
+    while (hlen > 0 && rc == 0) {
+	int impl = 0;
 	i = pgpLen(p, hlen, &plen);
 	if (i == 0 || i + plen > hlen)
 	    break;
@@ -402,7 +408,7 @@ static int pgpPrtSubType(const uint8_t *
 	if (p[0] & PGPSUBTYPE_CRITICAL)
 	    if (_print)
 		fprintf(stderr, " *CRITICAL*");
-	switch (*p) {
+	switch (*p & ~PGPSUBTYPE_CRITICAL) {
 	case PGPSUBTYPE_PREFER_SYMKEY:	/* preferred symmetric algorithms */
 	    for (i = 1; i < plen; i++)
 		pgpPrtVal(" ", pgpSymkeyTbl, p[i]);
@@ -420,6 +426,7 @@ static int pgpPrtSubType(const uint8_t *
 		pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
 	    break;
 	case PGPSUBTYPE_SIG_CREATE_TIME:
+	    impl = *p;
 	    if (!(_digp->saved & PGPDIG_SAVED_TIME) &&
 		(sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
 	    {
@@ -437,6 +444,7 @@ static int pgpPrtSubType(const uint8_t *
 	    break;
 
 	case PGPSUBTYPE_ISSUER_KEYID:	/* issuer key ID */
+	    impl = *p;
 	    if (!(_digp->saved & PGPDIG_SAVED_ID) &&
 		(sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
 	    {
@@ -474,10 +482,18 @@ static int pgpPrtSubType(const uint8_t *
 	    break;
 	}
 	pgpPrtNL();
+
+	if (!impl && (p[0] & PGPSUBTYPE_CRITICAL))
+	    rc = 1;
+
 	p += plen;
 	hlen -= plen;
     }
-    return (hlen != 0); /* non-zero hlen is an error */
+
+    if (hlen != 0)
+	rc = 1;
+
+    return rc;
 }
 
 pgpDigAlg pgpDigAlgFree(pgpDigAlg alg)
@@ -499,9 +515,9 @@ static int pgpPrtSigParams(pgpTag tag, u
     int i;
     pgpDigAlg sigalg = pgpSignatureNew(pubkey_algo);
 
-    for (i = 0; i < sigalg->mpis && p + 2 <= pend; i++) {
+    for (i = 0; i < sigalg->mpis && pend - p >= 2; i++) {
 	int mpil = pgpMpiLen(p);
-	if (p + mpil > pend)
+	if (pend - p < mpil)
 	    break;
 	if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) {
 	    if (sigalg->setmpi(sigalg, i, p))
@@ -523,12 +539,29 @@ static int pgpPrtSigParams(pgpTag tag, u
     return rc;
 }
 
+static int pgpGet(const uint8_t *s, size_t nbytes, const uint8_t *send,
+                 unsigned int *valp)
+{
+    int rc = -1;
+
+    *valp = 0;
+    if (nbytes <= 4 && send - s >= nbytes) {
+	unsigned int val = pgpGrab(s, nbytes);
+	if (send - s - nbytes >= val) {
+	    rc = 0;
+	    *valp = val;
+	}
+    }
+
+    return rc;
+}
+
 static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
 		     pgpDigParams _digp)
 {
     uint8_t version = h[0];
-    uint8_t * p;
-    size_t plen;
+    const uint8_t * p;
+    unsigned int plen;
     int rc;
 
     switch (version) {
@@ -570,6 +603,7 @@ static int pgpPrtSig(pgpTag tag, const u
     }	break;
     case 4:
     {   pgpPktSigV4 v = (pgpPktSigV4)h;
+	const uint8_t *const hend = h + hlen;
 
 	if (hlen <= sizeof(*v))
 	    return 1;
@@ -581,10 +615,11 @@ static int pgpPrtSig(pgpTag tag, const u
 	pgpPrtNL();
 
 	p = &v->hashlen[0];
-	plen = pgpGrab(v->hashlen, sizeof(v->hashlen));
+	if (pgpGet(v->hashlen, sizeof(v->hashlen), hend, &plen))
+	    return 1;
 	p += sizeof(v->hashlen);
 
-	if ((p + plen) > (h + hlen))
+	if ((p + plen) > hend)
 	    return 1;
 
 	if (_digp->pubkey_algo == 0) {
@@ -595,17 +630,19 @@ static int pgpPrtSig(pgpTag tag, const u
 	    return 1;
 	p += plen;
 
-	plen = pgpGrab(p,2);
+	if (pgpGet(p, 2, hend, &plen))
+	    return 1;
 	p += 2;
 
-	if ((p + plen) > (h + hlen))
+	if ((p + plen) > hend)
 	    return 1;
 
 	if (pgpPrtSubType(p, plen, v->sigtype, _digp))
 	    return 1;
 	p += plen;
 
-	plen = pgpGrab(p,2);
+	if (h + hlen - p < 2)
+	    return 1;
 	pgpPrtHex(" signhash16", p, 2);
 	pgpPrtNL();
 
@@ -618,7 +655,7 @@ static int pgpPrtSig(pgpTag tag, const u
 	}
 
 	p += 2;
-	if (p > (h + hlen))
+	if (p > hend)
 	    return 1;
 
 	rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
@@ -971,6 +1008,8 @@ int pgpPrtParams(const uint8_t * pkts, s
 	    break;
 
 	p += (pkt.body - pkt.head) + pkt.blen;
+	if (pkttype == PGPTAG_SIGNATURE)
+	    break;
     }
 
     rc = (digp && (p == pend)) ? 0 : -1;
