summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2016-11-25 12:12:40 +0200
committerPanu Matilainen <pmatilai@redhat.com>2016-11-25 12:40:05 +0200
commit67d0b787caef3e23317a84e9f286c751f09e2264 (patch)
tree860c8902a3b9b5113e195754a3692d34a74a7d79
parent6d2124ae90187878f4f8eb081db22c8c1b34d817 (diff)
downloadrpm-67d0b787caef3e23317a84e9f286c751f09e2264.tar.gz
Refactor headerImport() around struct hdrblob and API
Do the duck, bird and a monkey to flip headerImport() and hdrblobImport() around and upside down. Meaning every single path to read or otherwise import a header is now going through all the same validation and verification steps, whee! This also greatly simplifies the actual import since many of the calculations have already been done by the earlier steps. There aren't supposed to be regressions here but then I wouldn't exactly be shocked if there are some lurking nevertheless.
-rw-r--r--lib/header.c135
-rw-r--r--lib/header_internal.h3
2 files changed, 48 insertions, 90 deletions
diff --git a/lib/header.c b/lib/header.c
index 8844466b3..8b0fef791 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -848,93 +848,46 @@ int headerDel(Header h, rpmTagVal tag)
return 0;
}
-Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
+rpmRC hdrblobImport(hdrblob blob, int fast, Header *hdrp, char **emsg)
{
- const int32_t * ei = (int32_t *) blob;
- int32_t il = ntohl(ei[0]); /* index length */
- int32_t dl = ntohl(ei[1]); /* data length */
- unsigned int pvlen = sizeof(il) + sizeof(dl) +
- (il * sizeof(struct entryInfo_s)) + dl;;
Header h = NULL;
- entryInfo pe;
- unsigned char * dataStart;
- unsigned char * dataEnd;
indexEntry entry;
int rdlen;
- int fast = (flags & HEADERIMPORT_FAST);
- /* Sanity checks on header intro. */
- if (bsize && bsize != pvlen)
- goto errxit;
- if (hdrchkTags(il) || hdrchkData(dl) || pvlen >= headerMaxbytes)
- goto errxit;
-
- if (flags & HEADERIMPORT_COPY && bsize)
- ei = blob = memcpy(xmalloc(bsize), ei, bsize);
- h = headerCreate(blob, il);
-
- pe = (entryInfo) &ei[2];
- dataStart = (unsigned char *) (pe + il);
- dataEnd = dataStart + dl;
+ h = headerCreate(blob->ei, blob->il);
entry = h->index;
- if (!(htonl(pe->tag) < RPMTAG_HEADERI18NTABLE)) {
+ if (!(htonl(blob->pe->tag) < RPMTAG_HEADERI18NTABLE)) {
+ /* An original v3 header, create a legacy region entry for it */
h->flags |= HEADERFLAG_LEGACY;
entry->info.type = REGION_TAG_TYPE;
entry->info.tag = RPMTAG_HEADERIMAGE;
entry->info.count = REGION_TAG_COUNT;
- entry->info.offset = ((unsigned char *)pe - dataStart); /* negative offset */
-
- entry->data = pe;
- entry->length = pvlen - sizeof(il) - sizeof(dl);
- rdlen = regionSwab(entry+1, il, 0, pe,
- dataStart, dataEnd, entry->info.offset, fast);
- if (rdlen != dl)
+ entry->info.offset = ((unsigned char *)blob->pe - blob->dataStart); /* negative offset */
+
+ entry->data = blob->pe;
+ entry->length = blob->pvlen - sizeof(blob->il) - sizeof(blob->dl);
+ rdlen = regionSwab(entry+1, blob->il, 0, blob->pe,
+ blob->dataStart, blob->dataEnd,
+ entry->info.offset, fast);
+ if (rdlen != blob->dl)
goto errxit;
entry->rdlen = rdlen;
h->indexUsed++;
} else {
- int32_t rdl;
+ /* Either a v4 header or an "upgraded" v3 header with a legacy region */
int32_t ril;
h->flags &= ~HEADERFLAG_LEGACY;
-
- entry->info.type = htonl(pe->type);
- entry->info.count = htonl(pe->count);
- entry->info.tag = htonl(pe->tag);
-
- if (!ENTRY_IS_REGION(entry))
- goto errxit;
- if (entry->info.type != REGION_TAG_TYPE)
- goto errxit;
- if (entry->info.count != REGION_TAG_COUNT)
- goto errxit;
-
- { int off = ntohl(pe->offset);
-
- if (off) {
- size_t nb = REGION_TAG_COUNT;
- int32_t stei[nb];
- if (hdrchkRange(dl, (off + nb)))
- goto errxit;
- /* XXX Hmm, why the copy? */
- memcpy(&stei, dataStart + off, nb);
- rdl = -ntohl(stei[2]); /* negative offset */
- ril = rdl/sizeof(*pe);
- if (hdrchkTags(ril) || hdrchkData(rdl))
- goto errxit;
- } else {
- ril = il;
- rdl = (ril * sizeof(struct entryInfo_s));
- entry->info.tag = RPMTAG_HEADERIMAGE;
- }
- }
- entry->info.offset = -rdl; /* negative offset */
-
- entry->data = pe;
- entry->length = pvlen - sizeof(il) - sizeof(dl);
- rdlen = regionSwab(entry+1, ril-1, 0, pe+1,
- dataStart, dataEnd, entry->info.offset, fast);
+ ei2h(blob->pe, &entry->info);
+ ril = (entry->info.offset != 0) ? blob->ril : blob->il;
+
+ entry->info.offset = -(ril * sizeof(*blob->pe)); /* negative offset */
+ entry->data = blob->pe;
+ entry->length = blob->pvlen - sizeof(blob->il) - sizeof(blob->dl);
+ rdlen = regionSwab(entry+1, ril-1, 0, blob->pe+1,
+ blob->dataStart, blob->dataEnd,
+ entry->info.offset, fast);
if (rdlen < 0)
goto errxit;
entry->rdlen = rdlen;
@@ -945,8 +898,8 @@ Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
int rid = entry->info.offset+1;
/* Load dribble entries from region. */
- rdlen = regionSwab(newEntry, ne, rdlen, pe+ril,
- dataStart, dataEnd, rid, fast);
+ rdlen = regionSwab(newEntry, ne, rdlen, blob->pe+ril,
+ blob->dataStart, blob->dataEnd, rid, fast);
if (rdlen < 0)
goto errxit;
@@ -973,7 +926,7 @@ Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
rdlen += REGION_TAG_COUNT;
- if (rdlen != dl)
+ if (rdlen != blob->dl)
goto errxit;
}
@@ -981,17 +934,18 @@ Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
h->sorted = HEADERSORT_NONE;
headerSort(h);
h->flags |= HEADERFLAG_ALLOCATED;
+ if (hdrp)
+ *hdrp = h;
- return h;
+ return RPMRC_OK;
errxit:
if (h) {
- if (flags & HEADERIMPORT_COPY)
- free(h->blob);
free(h->index);
free(h);
+ rasprintf(emsg, _("hdr load: BAD"));
}
- return NULL;
+ return RPMRC_FAIL;
}
Header headerReload(Header h, rpmTagVal tag)
@@ -1982,7 +1936,7 @@ rpmRC hdrblobInit(const void *uh, size_t uc,
blob->dataEnd = blob->dataStart + blob->dl;
/* Is the blob the right size? */
- if (blob->uc > 0 && blob->pvlen != blob->uc) {
+ if (blob->pvlen >= headerMaxbytes || blob->pvlen != blob->uc) {
rasprintf(emsg, _("blob size(%zd): BAD, 8 + 16 * il(%d) + dl(%d)"),
blob->uc, blob->il, blob->dl);
goto exit;
@@ -2001,18 +1955,23 @@ exit:
return rc;
}
-rpmRC hdrblobImport(hdrblob blob, headerImportFlags flags,
- Header *hdrp, char **emsg)
+Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
{
- Header h = headerImport(blob->ei, blob->uc, flags);
+ Header h = NULL;
+ struct hdrblob_s hblob;
+ char *buf = NULL;
+ void * b = blob;
- if (h == NULL) {
- free(blob->ei);
- rasprintf(emsg, _("hdr load: BAD"));
- } else {
- *hdrp = h;
- }
- blob->ei = NULL;
+ if (flags & HEADERIMPORT_COPY && bsize)
+ b = memcpy(xmalloc(bsize), b, bsize);
- return (h != NULL) ? RPMRC_OK : RPMRC_FAIL;
+ /* Sanity checks on header intro. */
+ if (hdrblobInit(b, bsize, 0, 0, &hblob, &buf) == RPMRC_OK)
+ hdrblobImport(&hblob, (flags & HEADERIMPORT_FAST), &h, &buf);
+
+ if (h == NULL && b != blob)
+ free(b);
+ free(buf);
+
+ return h;
}
diff --git a/lib/header_internal.h b/lib/header_internal.h
index 76d1bd528..ec83c05be 100644
--- a/lib/header_internal.h
+++ b/lib/header_internal.h
@@ -57,8 +57,7 @@ RPM_GNUC_INTERNAL
rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrblob blob, char **emsg);
RPM_GNUC_INTERNAL
-rpmRC hdrblobImport(hdrblob blob, headerImportFlags flags,
- Header *hdrp, char **emsg);
+rpmRC hdrblobImport(hdrblob blob, int fast, Header *hdrp, char **emsg);
/** \ingroup header
* Set header instance (rpmdb record number)