--- configure.ac.orig	2022-09-08 14:42:23.225195766 +0000
+++ configure.ac	2022-09-08 14:42:28.781187580 +0000
@@ -27,7 +27,7 @@ AS=${AS-as}
 AC_SUBST(AS)
 if test "$ac_cv_c_compiler_gnu" = yes; then
     CFLAGS="$CFLAGS -fPIC -DPIC -D_GNU_SOURCE -D_REENTRANT -Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wno-char-subscripts"
-    cflags_to_try="-fno-strict-aliasing"
+    cflags_to_try="-fno-strict-aliasing -fno-strict-overflow -fno-delete-null-pointer-checks"
     AC_MSG_CHECKING([supported compiler flags])
     old_cflags=$CFLAGS
     echo
--- lib/package.c.orig	2022-09-08 14:42:23.249195730 +0000
+++ lib/package.c	2022-09-08 14:42:28.781187580 +0000
@@ -95,84 +95,68 @@ static int typeAlign[16] =  {
  */
 #define hdrchkRange(_dl, _off)		((_off) < 0 || (_off) > (_dl))
 
-void headerMergeLegacySigs(Header h, const Header sigh)
+/**
+ * Reasonableness check on count values.
+ * Most types have further restrictions, these are just the outer perimeter.
+ */
+#define hdrchkCount(_dl, _count) ((_count) < 1 || (_count) > (_dl))
+
+
+static struct taglate_s {
+    int_32 stag;
+    int_32 xtag;
+    int_32 count;
+    int quirk;
+    int type;
+} const xlateTags[] = {
+    { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1, 0, RPM_INT32_TYPE },
+    { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0, 0, RPM_BIN_TYPE },
+    { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16, 0, RPM_BIN_TYPE },
+    { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0, 0, RPM_BIN_TYPE },
+    /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0, 0, RPM_BIN_TYPE }, */ /* long obsolete, dont use */
+    { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1, 1, RPM_INT32_TYPE },
+    { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1, 0, RPM_STRING_TYPE },
+    { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0, 0, RPM_BIN_TYPE },
+    { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0, 0, RPM_BIN_TYPE },
+    { 0 }
+};
+
+static int headerMergeLegacySigsInternal(Header h, const Header sigh)
 {
     HFD_t hfd = (HFD_t) headerFreeData;
     HAE_t hae = (HAE_t) headerAddEntry;
-    HeaderIterator hi;
-    int_32 tag, type, count;
-    const void * ptr;
-    int xx;
+    HGE_t hge = (HGE_t) headerGetEntryMinMemory;
+    const struct taglate_s *xl;
 
-    for (hi = headerInitIterator(sigh);
-        headerNextIterator(hi, &tag, &type, &ptr, &count);
-        ptr = hfd(ptr, type))
-    {
-	switch (tag) {
-	/* XXX Translate legacy signature tag values. */
-	case RPMSIGTAG_SIZE:
-	    tag = RPMTAG_SIGSIZE;
-	    /*@switchbreak@*/ break;
-	case RPMSIGTAG_LEMD5_1:
-	    tag = RPMTAG_SIGLEMD5_1;
-	    /*@switchbreak@*/ break;
-	case RPMSIGTAG_PGP:
-	    tag = RPMTAG_SIGPGP;
-	    /*@switchbreak@*/ break;
-	case RPMSIGTAG_LEMD5_2:
-	    tag = RPMTAG_SIGLEMD5_2;
-	    /*@switchbreak@*/ break;
-	case RPMSIGTAG_MD5:
-	    tag = RPMTAG_SIGMD5;
-	    /*@switchbreak@*/ break;
-	case RPMSIGTAG_GPG:
-	    tag = RPMTAG_SIGGPG;
-	    /*@switchbreak@*/ break;
-	case RPMSIGTAG_PGP5:
-	    tag = RPMTAG_SIGPGP5;
-	    /*@switchbreak@*/ break;
-	case RPMSIGTAG_PAYLOADSIZE:
-	    tag = RPMTAG_ARCHIVESIZE;
-	    /*@switchbreak@*/ break;
-	case RPMSIGTAG_SHA1:
-	case RPMSIGTAG_DSA:
-	case RPMSIGTAG_RSA:
-	default:
-	    if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
-		continue;
-	    /*@switchbreak@*/ break;
-	}
-	if (ptr == NULL) continue;	/* XXX can't happen */
-	if (!headerIsEntry(h, tag)) {
-	    if (hdrchkType(type))
-		continue;
-	    if (count < 0 || hdrchkData(count))
-		continue;
-	    switch(type) {
-	    case RPM_NULL_TYPE:
-		continue;
-		/*@notreached@*/ /*@switchbreak@*/ break;
-	    case RPM_CHAR_TYPE:
-	    case RPM_INT8_TYPE:
-	    case RPM_INT16_TYPE:
-	    case RPM_INT32_TYPE:
-		if (count != 1)
-		    continue;
-		/*@switchbreak@*/ break;
-	    case RPM_STRING_TYPE:
-	    case RPM_BIN_TYPE:
-		if (count >= 16*1024)
-		    continue;
-		/*@switchbreak@*/ break;
-	    case RPM_STRING_ARRAY_TYPE:
-	    case RPM_I18NSTRING_TYPE:
-		continue;
-		/*@notreached@*/ /*@switchbreak@*/ break;
-	    }
- 	    xx = hae(h, tag, type, ptr, count);
+    for (xl = xlateTags; xl->stag; xl++) {
+	/* There mustn't be one in the main header */
+	if (headerIsEntry(h, xl->xtag)) {
+	    /* Some tags may exist in either header, but never both */
+	    if (!xl->quirk && headerIsEntry(sigh, xl->stag))
+		return xl->xtag;
+        }
+    }
+    for (xl = xlateTags; xl->stag; xl++) {
+	rpmTagType type;
+	void *data;
+	int_32 count;
+	if (!hge(sigh, xl->stag, &type, &data, &count))
+	    continue;
+	if (type != xl->type || count < 1 || count > 16*1024 || (xl->count && count != xl->count)) {
+	    if (type != RPM_BIN_TYPE)
+		hfd(data, type);
+	    return xl->xtag;
 	}
+	hae(h, xl->xtag, type, data, count);
+	if (type != RPM_BIN_TYPE)
+	    hfd(data, type);
     }
-    hi = headerFreeIterator(hi);
+    return 0;
+}
+
+void headerMergeLegacySigs(Header h, const Header sigh)
+{
+    (void)headerMergeLegacySigsInternal(h, sigh);
 }
 
 Header headerRegenSigHeader(const Header h, int noArchiveSize)
@@ -297,6 +281,8 @@ int headerVerifyInfo(int il, int dl, con
 
 	if (hdrchkType(info->type))
 	    return i;
+	if (hdrchkCount(dl, info->count))
+	    return i;
 	if (hdrchkAlign(info->type, info->offset))
 	    return i;
 	if (hdrchkRange(dl, info->offset))
@@ -328,8 +314,8 @@ rpmRC headerCheck(rpmts ts, const void *
     unsigned char buf[8*BUFSIZ];
     int_32 * ei = (int_32 *) uh;
 /*@-boundsread@*/
-    int_32 il = ntohl(ei[0]);
-    int_32 dl = ntohl(ei[1]);
+    int_32 il = ntohl((uint32_t)ei[0]);
+    int_32 dl = ntohl((uint32_t)ei[1]);
 /*@-castexpose@*/
     entryInfo pe = (entryInfo) &ei[2];
 /*@=castexpose@*/
@@ -358,7 +344,7 @@ rpmRC headerCheck(rpmts ts, const void *
 /*@=boundswrite@*/
 
     /* Is the blob the right size? */
-    if (uc > 0 && pvlen != uc) {
+    if (uc > 0 && (uc < 8 || pvlen != uc)) {
 	(void) snprintf(buf, sizeof(buf),
 		_("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
 		(int)uc, (int)il, (int)dl);
@@ -366,7 +352,7 @@ rpmRC headerCheck(rpmts ts, const void *
     }
 
     /* Check (and convert) the 1st tag element. */
-    xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
+    xx = il > 0 ? headerVerifyInfo(1, dl, pe, &entry->info, 0) : -1;
     if (xx != -1) {
 	(void) snprintf(buf, sizeof(buf),
 		_("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
@@ -687,7 +673,7 @@ rpmRC rpmReadHeader(rpmts ts, FD_t fd, H
 	goto exit;
     }
 /*@-boundsread@*/
-    il = ntohl(block[2]);
+    il = ntohl((uint32_t)block[2]);
 /*@=boundsread@*/
     if (hdrchkTags(il)) {
 	(void) snprintf(buf, sizeof(buf),
@@ -696,7 +682,7 @@ rpmRC rpmReadHeader(rpmts ts, FD_t fd, H
 	goto exit;
     }
 /*@-boundsread@*/
-    dl = ntohl(block[3]);
+    dl = ntohl((uint32_t)block[3]);
 /*@=boundsread@*/
     if (hdrchkData(dl)) {
 	(void) snprintf(buf, sizeof(buf),
@@ -1057,15 +1043,21 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t
 
 exit:
     if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
+	int tag;
 	/* Convert legacy headers on the fly ... */
 	legacyRetrofit(h, l);
 	
 	/* Append (and remap) signature tags to the metadata. */
-	headerMergeLegacySigs(h, sigh);
+	tag = headerMergeLegacySigsInternal(h, sigh);
+	if (tag) {
+	    rpmMessage(RPMMESS_ERROR, "%s: invalid signature tag (%d)\n", fn, tag);
+	    rc = RPMRC_FAIL;
+	}
 
 	/* Bump reference count for return. */
 /*@-boundswrite@*/
-	*hdrp = headerLink(h);
+	if (rc != RPMRC_FAIL)
+	    *hdrp = headerLink(h);
 /*@=boundswrite@*/
     }
     h = headerFree(h);
--- lib/signature.c.orig	2022-09-08 14:42:23.249195730 +0000
+++ lib/signature.c	2022-09-08 14:42:28.785187576 +0000
@@ -194,7 +194,7 @@ rpmRC rpmReadSignature(FD_t fd, Header *
 	goto exit;
     }
 /*@-boundsread@*/
-    il = ntohl(block[2]);
+    il = ntohl((uint32_t)block[2]);
 /*@=boundsread@*/
     if (il < 0 || il > 32) {
 	(void) snprintf(buf, sizeof(buf),
@@ -202,7 +202,7 @@ rpmRC rpmReadSignature(FD_t fd, Header *
 	goto exit;
     }
 /*@-boundsread@*/
-    dl = ntohl(block[3]);
+    dl = ntohl((uint32_t)block[3]);
 /*@=boundsread@*/
     if (dl < 0 || dl > 8192) {
 	(void) snprintf(buf, sizeof(buf),
@@ -227,7 +227,7 @@ rpmRC rpmReadSignature(FD_t fd, Header *
     }
     
     /* Check (and convert) the 1st tag element. */
-    xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
+    xx = il > 0 ? headerVerifyInfo(1, dl, pe, &entry->info, 0) : -1;
     if (xx != -1) {
 	(void) snprintf(buf, sizeof(buf),
 		_("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
--- rpmdb/header.c.orig	2022-09-08 14:42:23.249195730 +0000
+++ rpmdb/header.c	2022-09-08 14:43:21.253110285 +0000
@@ -31,6 +31,12 @@ int _hdr_debug = 0;
 #define PARSER_IN_ARRAY 1
 #define PARSER_IN_EXPR  2
 
+/**
+ * Reasonableness check on count values.
+ * Most types have further restrictions, these are just the outer perimeter.
+ */
+#define hdrchkCount(_dl, _count) ((_count) < 1 || (_count) > (_dl))
+
 /** \ingroup header
  */
 /*@observer@*/ /*@unchecked@*/
@@ -417,6 +423,8 @@ static int dataLength(int_32 type, hPTR_
 			return -1;
 		    length++;
 		}
+		if (se && s > se)
+		    return -1;
 /*@=boundsread@*/
 	    }
 	} else {
@@ -499,6 +507,8 @@ static int regionSwab(/*@null@*/ indexEn
 
 	if (hdrchkType(ie.info.type))
 	    return -1;
+	if (dataEnd && hdrchkCount((dataEnd - dataStart), ie.info.count))
+	    return -1;
 	if (hdrchkData(ie.info.count))
 	    return -1;
 	if (hdrchkData(ie.info.offset))
@@ -993,8 +1003,8 @@ Header headerLoad(/*@kept@*/ void * uh)
 	/*@modifies uh @*/
 {
     int_32 * ei = (int_32 *) uh;
-    int_32 il = ntohl(ei[0]);		/* index length */
-    int_32 dl = ntohl(ei[1]);		/* data length */
+    int_32 il = ntohl((uint32_t)ei[0]);		/* index length */
+    int_32 dl = ntohl((uint32_t)ei[1]);		/* data length */
     /*@-sizeoftype@*/
     size_t pvlen = sizeof(il) + sizeof(dl) +
                (il * sizeof(struct entryInfo_s)) + dl;
@@ -1037,7 +1047,7 @@ Header headerLoad(/*@kept@*/ void * uh)
      * XXX XFree86-libs, ash, and pdksh from Red Hat 5.2 have bogus
      * %verifyscript tag that needs to be diddled.
      */
-    if (ntohl(pe->tag) == 15 &&
+    if (il && ntohl(pe->tag) == 15 &&
 	ntohl(pe->type) == RPM_STRING_TYPE &&
 	ntohl(pe->count) == 1)
     {
@@ -1046,7 +1056,7 @@ Header headerLoad(/*@kept@*/ void * uh)
 
     entry = h->index;
     i = 0;
-    if (!(htonl(pe->tag) < HEADER_I18NTABLE)) {
+    if (!il || !(htonl(pe->tag) < HEADER_I18NTABLE)) {
 	h->flags |= HEADERFLAG_LEGACY;
 	entry->info.type = REGION_TAG_TYPE;
 	entry->info.tag = HEADER_IMAGE;
@@ -1060,6 +1070,8 @@ Header headerLoad(/*@kept@*/ void * uh)
 	/*@=assignexpose@*/
 	entry->length = pvlen - sizeof(il) - sizeof(dl);
 	rdlen = regionSwab(entry+1, il, 0, pe, dataStart, dataEnd, entry->info.offset);
+	if (rdlen < 0)
+	    goto errxit;
 #if 0	/* XXX don't check, the 8/98 i18n bug fails here. */
 	if (rdlen != dl)
 	    goto errxit;
