Test for file data tag sanity in fnTag() extensions

- Basename and dirindex counts must be equal, dirnames count must be
  larger than zero and no larger than number of basenames. Check
  that directory indexes are within range. Additionally file states
  array size, if used, must equal to the genaral file count.
This commit is contained in:
Panu Matilainen 2012-02-21 16:24:18 +02:00
parent e3fdb8a45a
commit 97e72eaaea
1 changed files with 38 additions and 22 deletions

View File

@ -39,14 +39,13 @@ struct headerTagFunc_s {
*/
static int fnTag(Header h, rpmTag tagN, int withstate, rpmtd td)
{
const char **baseNames, **dirNames, **fileNames;
const char **baseNames, **dirNames;
const char *fileStates = NULL;
uint32_t *dirIndexes;
rpm_count_t count, retcount;
rpm_count_t count, retcount, dncount;
size_t size = 0;
rpmTag dirNameTag = RPMTAG_DIRNAMES;
rpmTag dirIndexesTag = RPMTAG_DIRINDEXES;
char * t;
int i, j;
int rc = 0; /* assume failure */
struct rpmtd_s bnames, dnames, dixs, fstates;
@ -64,17 +63,28 @@ static int fnTag(Header h, rpmTag tagN, int withstate, rpmtd td)
(void) headerGet(h, dirIndexesTag, &dixs, HEADERGET_MINMEM);
retcount = count = rpmtdCount(&bnames);
baseNames = bnames.data;
dirNames = dnames.data;
dirIndexes = dixs.data;
dncount = rpmtdCount(&dnames);
/* Basic sanity checking for our interrelated tags */
if (rpmtdCount(&dixs) != count || dncount < 1 || dncount > count)
td->flags |= RPMTD_INVALID;
if (withstate) {
/* no recorded states means no installed files */
if (!headerGet(h, RPMTAG_FILESTATES, &fstates, HEADERGET_MINMEM)) {
if (!headerGet(h, RPMTAG_FILESTATES, &fstates, HEADERGET_MINMEM))
goto exit;
if (rpmtdCount(&fstates) != count)
td->flags |= RPMTD_INVALID;
fileStates = fstates.data;
}
if (td->flags & RPMTD_INVALID)
goto exit;
baseNames = bnames.data;
dirNames = dnames.data;
dirIndexes = dixs.data;
/*
* fsm, psm and rpmfi assume the data is stored in a single allocation
* block, until those assumptions are removed we need to jump through
@ -85,26 +95,32 @@ static int fnTag(Header h, rpmTag tagN, int withstate, rpmtd td)
retcount--;
continue;
}
/* Sanity check directory indexes are within bounds */
if (dirIndexes[i] >= dncount) {
td->flags |= RPMTD_INVALID;
break;
}
size += strlen(baseNames[i]) + strlen(dirNames[dirIndexes[i]]) + 1;
}
size += sizeof(*fileNames) * retcount;
fileNames = xmalloc(size);
t = ((char *) fileNames) + (sizeof(*fileNames) * retcount);
for (i = 0, j = 0; i < count; i++) {
if (fileStates && !RPMFILE_IS_INSTALLED(fileStates[i]))
continue;
fileNames[j++] = t;
t = stpcpy( stpcpy(t, dirNames[dirIndexes[i]]), baseNames[i]);
*t++ = '\0';
if (!(td->flags & RPMTD_INVALID)) {
char **fileNames = xmalloc(size + (sizeof(*fileNames) * retcount));
char *t = ((char *) fileNames) + (sizeof(*fileNames) * retcount);
for (i = 0, j = 0; i < count; i++) {
if (fileStates && !RPMFILE_IS_INSTALLED(fileStates[i]))
continue;
fileNames[j++] = t;
t = stpcpy( stpcpy(t, dirNames[dirIndexes[i]]), baseNames[i]);
*t++ = '\0';
}
td->data = fileNames;
td->count = retcount;
td->type = RPM_STRING_ARRAY_TYPE;
td->flags |= RPMTD_ALLOCED;
rc = 1;
}
td->data = fileNames;
td->count = retcount;
td->type = RPM_STRING_ARRAY_TYPE;
td->flags |= RPMTD_ALLOCED;
rc = 1;
exit:
rpmtdFreeData(&bnames);
rpmtdFreeData(&dnames);