diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2012-02-21 16:24:18 +0200 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2012-02-21 16:24:18 +0200 |
commit | 97e72eaaea49008a2f05b806f95be0db3db3ad95 (patch) | |
tree | fe06b37aaffcb93121cecc7c14a15d422927545d /lib/tagexts.c | |
parent | e3fdb8a45a051e95479c2353522691e3dc4e7e2b (diff) | |
download | librpm-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.c | 60 |
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); |