Add an enhanced interface for loading, aka importing, headers
authorPanu Matilainen <pmatilai@redhat.com>
Wed, 30 Nov 2011 07:12:48 +0000 (09:12 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Wed, 30 Nov 2011 08:41:00 +0000 (10:41 +0200)
- Unlike headerLoad(), headerImport() takes a blob size argument
  to allow sanity checking the size calculated from the blob itself
  against the "physical" passed-in blob size so its a bit safer.
  Note that header size is capped by various things - its not size_t.
- headerImport() also takes a flags argument to allow controlling
  various aspects of importing.
- Implement "take copy of blob" as a flag to headerImport(), push
  the copying into headerCreate() where we already know the blob
  size, avoiding the need to do double-calculations on headerCopyLoad()..
- headerLoad() and headerCopyLoad() are now just compat wrappers
  around the new interface.

lib/header.c
lib/header.h

index 6458f41..9ebf592 100644 (file)
@@ -154,11 +154,11 @@ Header headerFree(Header h)
     return NULL;
 }
 
-static Header headerCreate(void *blob, int32_t indexLen)
+static Header headerCreate(void *blob, unsigned int pvlen, int32_t indexLen)
 {
     Header h = xcalloc(1, sizeof(*h));
-    h->blob = blob;
     if (blob) {
+       h->blob = (pvlen > 0) ? memcpy(xmalloc(pvlen), blob, pvlen) : blob;
        h->indexAlloced = indexLen + 1;
        h->indexUsed = indexLen;
     } else {
@@ -178,7 +178,7 @@ static Header headerCreate(void *blob, int32_t indexLen)
 
 Header headerNew(void)
 {
-    return headerCreate(NULL, 0);
+    return headerCreate(NULL, 0, 0);
 }
 
 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
@@ -766,13 +766,13 @@ int headerDel(Header h, rpmTagVal tag)
     return 0;
 }
 
-Header headerLoad(void * uh)
+Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
 {
-    int32_t * ei = (int32_t *) uh;
+    const int32_t * ei = (int32_t *) blob;
     int32_t il = ntohl(ei[0]);         /* index length */
     int32_t dl = ntohl(ei[1]);         /* data length */
-    size_t pvlen = sizeof(il) + sizeof(dl) +
-               (il * sizeof(struct entryInfo_s)) + dl;
+    unsigned int pvlen = sizeof(il) + sizeof(dl) +
+                   (il * sizeof(struct entryInfo_s)) + dl;;
     Header h = NULL;
     entryInfo pe;
     unsigned char * dataStart;
@@ -781,15 +781,18 @@ Header headerLoad(void * uh)
     int rdlen;
 
     /* Sanity checks on header intro. */
-    if (hdrchkTags(il) || hdrchkData(dl))
+    if (bsize && bsize != pvlen)
        goto errxit;
+    if (hdrchkTags(il) || hdrchkData(dl) || pvlen >= headerMaxbytes)
+       goto errxit;
+
+    h = headerCreate(blob, (flags & HEADERIMPORT_COPY) ? pvlen : 0, il);
 
+    ei = h->blob; /* In case we had to copy */
     pe = (entryInfo) &ei[2];
     dataStart = (unsigned char *) (pe + il);
     dataEnd = dataStart + dl;
 
-    h = headerCreate(uh, il);
-
     entry = h->index;
     if (!(htonl(pe->tag) < RPMTAG_HEADERI18NTABLE)) {
        h->flags |= HEADERFLAG_LEGACY;
@@ -894,6 +897,8 @@ Header headerLoad(void * uh)
 
 errxit:
     if (h) {
+       if (flags & HEADERIMPORT_COPY)
+           free(h->blob);
        free(h->index);
        free(h);
     }
@@ -920,22 +925,15 @@ Header headerReload(Header h, rpmTagVal tag)
     return nh;
 }
 
-Header headerCopyLoad(const void * uh)
+Header headerLoad(void * uh)
 {
-    int32_t * ei = (int32_t *) uh;
-    int32_t il = ntohl(ei[0]);         /* index length */
-    int32_t dl = ntohl(ei[1]);         /* data length */
-    size_t pvlen = sizeof(il) + sizeof(dl) +
-                       (il * sizeof(struct entryInfo_s)) + dl;
-    Header h = NULL;
+    return headerImport(uh, 0, 0);
+}
 
-    /* Sanity checks on header intro. */
-    if (!(hdrchkTags(il) || hdrchkData(dl)) && pvlen < headerMaxbytes) {
-       void * nuh = memcpy(xmalloc(pvlen), uh, pvlen);
-       if ((h = headerLoad(nuh)) == NULL)
-           free(nuh);
-    }
-    return h;
+Header headerCopyLoad(const void * uh)
+{
+    /* Discards const but that's ok as we'll take a copy */
+    return headerImport((void *)uh, 0, HEADERIMPORT_COPY);
 }
 
 Header headerRead(FD_t fd, int magicp)
index a9160fc..fdd6c99 100644 (file)
@@ -110,6 +110,7 @@ Header headerCopy(Header h);
 
 /** \ingroup header
  * Convert header to in-memory representation.
+ * @deprecated         Use headerImport() instead
  * @param uh           on-disk header blob (i.e. with offsets)
  * @return             header
  */
@@ -117,11 +118,27 @@ Header headerLoad(void * uh);
 
 /** \ingroup header
  * Make a copy and convert header to in-memory representation.
+ * @deprecated         Use headerImport() instead
  * @param uh           on-disk header blob (i.e. with offsets)
  * @return             header
  */
 Header headerCopyLoad(const void * uh);
 
+enum headerImportFlags_e {
+    HEADERIMPORT_COPY          = (1 << 0), /* Make copy of blob on import? */
+};
+
+typedef rpmFlags headerImportFlags;
+
+/** \ingroup header
+ * Import header to in-memory representation.
+ * @param blob         on-disk header blob (i.e. with offsets)
+ * @param bsize                on-disk header blob size in bytes (0 if unknown)
+ * @param flags                flags to control operation
+ * @return             header
+ */
+Header headerImport(void *blob, unsigned int bsize, headerImportFlags flags);
+
 /** \ingroup header
  * Read (and load) header from file handle.
  * @param fd           file handle