int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate) { entryInfo pe = (entryInfo) pev; entryInfo info = iv; int i; for (i = 0; i < il; i++) { info->tag = ntohl(pe[i].tag); info->type = ntohl(pe[i].type); info->offset = ntohl(pe[i].offset); if (negate) info->offset = -info->offset; info->count = ntohl(pe[i].count); if (hdrchkType(info->type)) return i; if (hdrchkAlign(info->type, info->offset)) return i; if (hdrchkRange(dl, info->offset)) return i; if (hdrchkData(info->count)) return i; } return -1; }
static int intAddEntry(Header h, rpmtd td) { indexEntry entry; rpm_data_t data; int length; /* Count must always be >= 1 for headerAddEntry. */ if (td->count <= 0) return 0; if (hdrchkType(td->type)) return 0; if (hdrchkData(td->count)) return 0; length = 0; data = grabData(td->type, td->data, td->count, &length); if (data == NULL || length <= 0) return 0; /* Allocate more index space if necessary */ if (h->indexUsed == h->indexAlloced) { h->indexAlloced += INDEX_MALLOC_SIZE; h->index = xrealloc(h->index, h->indexAlloced * sizeof(*h->index)); } /* Fill in the index */ entry = h->index + h->indexUsed; entry->info.tag = td->tag; entry->info.type = td->type; entry->info.count = td->count; entry->info.offset = 0; entry->data = data; entry->length = length; if (h->indexUsed > 0 && td->tag < h->index[h->indexUsed-1].info.tag) h->flags &= ~HEADERFLAG_SORTED; h->indexUsed++; return 1; }
/** \ingroup header * Swap int32_t and int16_t arrays within header region. * * If a header region tag is in the set to be swabbed, as the data for a * a header region is located after all other tag data. * * @param entry header entry * @param il no. of entries * @param dl start no. bytes of data * @param pe header physical entry pointer (swapped) * @param dataStart header data start * @param dataEnd header data end * @param regionid region offset * @param fast use offsets for data sizes if possible * @return no. bytes of data in region, -1 on error */ static int regionSwab(indexEntry entry, int il, int dl, entryInfo pe, unsigned char * dataStart, const unsigned char * dataEnd, int regionid, int fast) { if ((entry != NULL && regionid >= 0) || (entry == NULL && regionid != 0)) return -1; for (; il > 0; il--, pe++) { struct indexEntry_s ie; ie.info.tag = ntohl(pe->tag); ie.info.type = ntohl(pe->type); ie.info.count = ntohl(pe->count); ie.info.offset = ntohl(pe->offset); if (hdrchkType(ie.info.type)) return -1; if (hdrchkData(ie.info.count)) return -1; if (hdrchkData(ie.info.offset)) return -1; if (hdrchkAlign(ie.info.type, ie.info.offset)) return -1; ie.data = dataStart + ie.info.offset; if (dataEnd && (unsigned char *)ie.data >= dataEnd) return -1; if (fast && il > 1) { ie.length = ntohl(pe[1].offset) - ie.info.offset; } else { ie.length = dataLength(ie.info.type, ie.data, ie.info.count, 1, dataEnd); } if (ie.length < 0 || hdrchkData(ie.length)) return -1; ie.rdlen = 0; if (entry) { ie.info.offset = regionid; *entry = ie; /* structure assignment */ entry++; } /* Alignment */ dl += alignDiff(ie.info.type, dl); /* Perform endian conversions */ switch (ntohl(pe->type)) { case RPM_INT64_TYPE: { uint64_t * it = ie.data; for (; ie.info.count > 0; ie.info.count--, it += 1) { if (dataEnd && ((unsigned char *)it) >= dataEnd) return -1; *it = htonll(*it); } } break; case RPM_INT32_TYPE: { int32_t * it = ie.data; for (; ie.info.count > 0; ie.info.count--, it += 1) { if (dataEnd && ((unsigned char *)it) >= dataEnd) return -1; *it = htonl(*it); } } break; case RPM_INT16_TYPE: { int16_t * it = ie.data; for (; ie.info.count > 0; ie.info.count--, it += 1) { if (dataEnd && ((unsigned char *)it) >= dataEnd) return -1; *it = htons(*it); } } break; } dl += ie.length; } return dl; }
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; void * pv = uh; Header h = NULL; entryInfo pe; unsigned char * dataStart; unsigned char * dataEnd; indexEntry entry; int rdlen; /* Sanity checks on header intro. */ if (hdrchkTags(il) || hdrchkData(dl)) goto errxit; ei = (int32_t *) pv; pe = (entryInfo) &ei[2]; dataStart = (unsigned char *) (pe + il); dataEnd = dataStart + dl; h = xcalloc(1, sizeof(*h)); h->blob = uh; h->indexAlloced = il + 1; h->indexUsed = il; h->instance = 0; h->index = xcalloc(h->indexAlloced, sizeof(*h->index)); h->flags |= HEADERFLAG_SORTED; h->nrefs = 0; h = headerLink(h); entry = h->index; if (!(htonl(pe->tag) < HEADER_I18NTABLE)) { h->flags |= HEADERFLAG_LEGACY; entry->info.type = REGION_TAG_TYPE; entry->info.tag = HEADER_IMAGE; 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); if (rdlen != dl) goto errxit; entry->rdlen = rdlen; h->indexUsed++; } else { int32_t rdl; int32_t ril; h->flags &= ~HEADERFLAG_LEGACY; entry->info.type = htonl(pe->type); entry->info.count = htonl(pe->count); if (hdrchkType(entry->info.type)) goto errxit; if (hdrchkTags(entry->info.count)) goto errxit; { int off = ntohl(pe->offset); if (hdrchkData(off)) goto errxit; if (off) { size_t nb = REGION_TAG_COUNT; int32_t stei[nb]; /* 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; entry->info.tag = htonl(pe->tag); } else { ril = il; rdl = (ril * sizeof(struct entryInfo_s)); entry->info.tag = HEADER_IMAGE; } } 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); if (rdlen < 0) goto errxit; entry->rdlen = rdlen; if (ril < h->indexUsed) { indexEntry newEntry = entry + ril; int ne = (h->indexUsed - ril); int rid = entry->info.offset+1; int rc; /* Load dribble entries from region. */ rc = regionSwab(newEntry, ne, 0, pe+ril, dataStart, dataEnd, rid); if (rc < 0) goto errxit; rdlen += rc; { indexEntry firstEntry = newEntry; int save = h->indexUsed; int j; /* Dribble entries replace duplicate region entries. */ h->indexUsed -= ne; for (j = 0; j < ne; j++, newEntry++) { (void) headerDel(h, newEntry->info.tag); if (newEntry->info.tag == RPMTAG_BASENAMES) (void) headerDel(h, RPMTAG_OLDFILENAMES); } /* If any duplicate entries were replaced, move new entries down. */ if (h->indexUsed < (save - ne)) { memmove(h->index + h->indexUsed, firstEntry, (ne * sizeof(*entry))); } h->indexUsed += ne; } } } h->flags &= ~HEADERFLAG_SORTED; headerSort(h); h->flags |= HEADERFLAG_ALLOCATED; return h; errxit: if (h) { h->index = _free(h->index); h = _free(h); } return h; }
/** \ingroup header * Swap int32_t and int16_t arrays within header region. * * If a header region tag is in the set to be swabbed, as the data for a * a header region is located after all other tag data. * * @param entry header entry * @param il no. of entries * @param dl start no. bytes of data * @param pe header physical entry pointer (swapped) * @param dataStart header data start * @param dataEnd header data end * @param regionid region offset * @return no. bytes of data in region, -1 on error */ static int regionSwab(indexEntry entry, int il, int dl, entryInfo pe, unsigned char * dataStart, const unsigned char * dataEnd, int regionid) { for (; il > 0; il--, pe++) { struct indexEntry_s ie; rpmTagType type; ie.info.tag = ntohl(pe->tag); ie.info.type = ntohl(pe->type); ie.info.count = ntohl(pe->count); ie.info.offset = ntohl(pe->offset); if (hdrchkType(ie.info.type)) return -1; if (hdrchkData(ie.info.count)) return -1; if (hdrchkData(ie.info.offset)) return -1; if (hdrchkAlign(ie.info.type, ie.info.offset)) return -1; ie.data = dataStart + ie.info.offset; if (dataEnd && (unsigned char *)ie.data >= dataEnd) return -1; ie.length = dataLength(ie.info.type, ie.data, ie.info.count, 1, dataEnd); if (ie.length < 0 || hdrchkData(ie.length)) return -1; ie.rdlen = 0; if (entry) { ie.info.offset = regionid; *entry = ie; /* structure assignment */ entry++; } /* Alignment */ type = ie.info.type; if (typeSizes[type] > 1) { unsigned diff = typeSizes[type] - (dl % typeSizes[type]); if (diff != typeSizes[type]) { dl += diff; } } /* Perform endian conversions */ switch (ntohl(pe->type)) { case RPM_INT64_TYPE: { uint64_t * it = ie.data; for (; ie.info.count > 0; ie.info.count--, it += 1) { if (dataEnd && ((unsigned char *)it) >= dataEnd) return -1; *it = htonll(*it); } } break; case RPM_INT32_TYPE: { int32_t * it = ie.data; for (; ie.info.count > 0; ie.info.count--, it += 1) { if (dataEnd && ((unsigned char *)it) >= dataEnd) return -1; *it = htonl(*it); } } break; case RPM_INT16_TYPE: { int16_t * it = ie.data; for (; ie.info.count > 0; ie.info.count--, it += 1) { if (dataEnd && ((unsigned char *)it) >= dataEnd) return -1; *it = htons(*it); } } break; } dl += ie.length; } return dl; }
void headerMergeLegacySigs(Header h, const Header sigh) { HeaderIterator hi; struct rpmtd_s td; hi = headerInitIterator(sigh); for (; headerNext(hi, &td); rpmtdFreeData(&td)) { switch (td.tag) { /* XXX Translate legacy signature tag values. */ case RPMSIGTAG_SIZE: td.tag = RPMTAG_SIGSIZE; break; case RPMSIGTAG_PGP: td.tag = RPMTAG_SIGPGP; break; case RPMSIGTAG_MD5: td.tag = RPMTAG_SIGMD5; break; case RPMSIGTAG_GPG: td.tag = RPMTAG_SIGGPG; break; case RPMSIGTAG_PGP5: td.tag = RPMTAG_SIGPGP5; break; case RPMSIGTAG_PAYLOADSIZE: td.tag = RPMTAG_ARCHIVESIZE; break; case RPMSIGTAG_SHA1: case RPMSIGTAG_DSA: case RPMSIGTAG_RSA: default: if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE)) continue; break; } if (td.data == NULL) continue; /* XXX can't happen */ if (!headerIsEntry(h, td.tag)) { if (hdrchkType(td.type)) continue; if (td.count < 0 || hdrchkData(td.count)) continue; switch(td.type) { case RPM_NULL_TYPE: continue; break; case RPM_CHAR_TYPE: case RPM_INT8_TYPE: case RPM_INT16_TYPE: case RPM_INT32_TYPE: case RPM_INT64_TYPE: if (td.count != 1) continue; break; case RPM_STRING_TYPE: case RPM_BIN_TYPE: if (td.count >= 16*1024) continue; break; case RPM_STRING_ARRAY_TYPE: case RPM_I18NSTRING_TYPE: continue; break; } (void) headerPut(h, &td, HEADERPUT_DEFAULT); } } hi = headerFreeIterator(hi); }