summaryrefslogtreecommitdiff
path: root/lib/tagexts.c
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2012-02-21 16:24:18 +0200
committerPanu Matilainen <pmatilai@redhat.com>2012-02-21 16:24:18 +0200
commit97e72eaaea49008a2f05b806f95be0db3db3ad95 (patch)
treefe06b37aaffcb93121cecc7c14a15d422927545d /lib/tagexts.c
parente3fdb8a45a051e95479c2353522691e3dc4e7e2b (diff)
downloadlibrpm-tizen-97e72eaaea49008a2f05b806f95be0db3db3ad95.tar.gz
librpm-tizen-97e72eaaea49008a2f05b806f95be0db3db3ad95.tar.bz2
librpm-tizen-97e72eaaea49008a2f05b806f95be0db3db3ad95.zip
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.
Diffstat (limited to 'lib/tagexts.c')
-rw-r--r--lib/tagexts.c60
1 files changed, 38 insertions, 22 deletions
diff --git a/lib/tagexts.c b/lib/tagexts.c
index 19733f857..29b2bae9f 100644
--- a/lib/tagexts.c
+++ b/lib/tagexts.c
@@ -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,25 +95,31 @@ 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);