diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2010-11-29 15:56:55 +0200 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2010-11-29 15:56:55 +0200 |
commit | 9173e0f85972849df37dd6b5f3bb38c98730d4dc (patch) | |
tree | 0e36a1b925a3a473c6c6a228b3a678691e16cc86 /lib | |
parent | 8c925108fb90ebb0394874adbc1078d213cc40cf (diff) | |
download | librpm-tizen-9173e0f85972849df37dd6b5f3bb38c98730d4dc.tar.gz librpm-tizen-9173e0f85972849df37dd6b5f3bb38c98730d4dc.tar.bz2 librpm-tizen-9173e0f85972849df37dd6b5f3bb38c98730d4dc.zip |
Fix long-standing segfault on unknown tags on header iteration queries
- The simple and stupid tag cache was a bit too simple, failing
to deal with unknown tags larger than our own tag table correctly.
Use a hash table instead which is a far better suited for the
sparse tag numbers anyway.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/headerfmt.c | 57 |
1 files changed, 26 insertions, 31 deletions
diff --git a/lib/headerfmt.c b/lib/headerfmt.c index e030920e5..49c7047d5 100644 --- a/lib/headerfmt.c +++ b/lib/headerfmt.c @@ -61,13 +61,22 @@ struct sprintfToken_s { } u; }; +#define HASHTYPE tagCache +#define HTKEYTYPE rpmTagVal +#define HTDATATYPE rpmtd +#include "lib/rpmhash.H" +#include "lib/rpmhash.C" +#undef HASHTYPE +#undef HTKEYTYPE +#undef HTDATATYPE + /** */ typedef struct headerSprintfArgs_s { Header h; char * fmt; const char * errmsg; - rpmtd *cache; + tagCache cache; sprintfToken format; HeaderIterator hi; char * val; @@ -566,14 +575,10 @@ static int parseExpression(headerSprintfArgs hsa, sprintfToken token, return 0; } -static rpmtd getCached(rpmtd *cache, rpmTagVal tag) +static rpmtd getCached(tagCache cache, rpmTagVal tag) { - rpmtd td = NULL; - - if (tag >= RPMTAG_HEADERIMAGE && tag < RPMTAG_FIRSTFREE_TAG && cache[tag]) { - td = cache[tag]; - } - return td; + rpmtd *res = NULL; + return tagCacheGetEntry(cache, tag, &res, NULL, NULL) ? res[0] : NULL; } /** @@ -595,7 +600,7 @@ static rpmtd getData(headerSprintfArgs hsa, rpmTagVal tag) rpmtdFree(td); return NULL; } - hsa->cache[tag] = td; + tagCacheAddEntry(hsa->cache, tag, td); } return td; @@ -778,30 +783,20 @@ static char * singleSprintf(headerSprintfArgs hsa, sprintfToken token, return (hsa->val + hsa->vallen); } -/** - * Create tag data cache. - * This allocates much more space than necessary but playing it - * simple and stupid for now. - */ -static rpmtd *cacheCreate(void) +static int tagCmp(rpmTagVal a, rpmTagVal b) { - rpmtd *cache = xcalloc(RPMTAG_FIRSTFREE_TAG, sizeof(*cache)); - return cache; + return (a != b); } -/** - * Free tag data cache contents and destroy cache. - */ -static rpmtd *cacheFree(rpmtd *cache) +static unsigned int tagId(rpmTagVal tag) { - rpmtd *td = cache; - for (int i = 0; i < RPMTAG_FIRSTFREE_TAG; i++, td++) { - if (*td) { - rpmtdFreeData(*td); - rpmtdFree(*td); - } - } - free(cache); + return tag; +} + +static rpmtd tagFree(rpmtd td) +{ + rpmtdFreeData(td); + rpmtdFree(td); return NULL; } @@ -822,7 +817,7 @@ char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg) if (parseFormat(&hsa, hsa.fmt, &hsa.format, &hsa.numTokens, NULL, PARSER_BEGIN)) goto exit; - hsa.cache = cacheCreate(); + hsa.cache = tagCacheCreate(128, tagId, tagCmp, NULL, tagFree); hsa.val = xstrdup(""); tag = @@ -860,7 +855,7 @@ char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg) if (hsa.val != NULL && hsa.vallen < hsa.alloced) hsa.val = xrealloc(hsa.val, hsa.vallen+1); - hsa.cache = cacheFree(hsa.cache); + hsa.cache = tagCacheFree(hsa.cache); hsa.format = freeFormat(hsa.format, hsa.numTokens); exit: |