summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2010-11-29 15:56:55 +0200
committerPanu Matilainen <pmatilai@redhat.com>2010-11-29 15:56:55 +0200
commit9173e0f85972849df37dd6b5f3bb38c98730d4dc (patch)
tree0e36a1b925a3a473c6c6a228b3a678691e16cc86 /lib
parent8c925108fb90ebb0394874adbc1078d213cc40cf (diff)
downloadlibrpm-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.c57
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: