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:
parent
e3fdb8a45a
commit
97e72eaaea
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue