Add guards that abort if an overflow is about to happen

Related: RHEL-128441
This commit is contained in:
Aleš Matěj 2026-07-28 14:34:47 +02:00
parent 2fa3970fa7
commit ff8b649c41
4 changed files with 779 additions and 0 deletions

View File

@ -0,0 +1,281 @@
From 5da52ee473f9af964d5131ace7fbd6841b54f2ec Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Tue, 28 Apr 2026 14:35:11 +0200
Subject: [PATCH 1/3] Also guard against block size overflows
---
src/pool.c | 2 ++
src/repo.c | 10 +++++++++-
src/repo_solv.c | 47 ++++++++++++++++++++++++++++-------------------
src/repodata.c | 5 ++++-
src/strpool.c | 17 ++++++++++++++++-
src/util.c | 10 ++++++++++
src/util.h | 5 +++++
7 files changed, 74 insertions(+), 22 deletions(-)
diff --git a/src/pool.c b/src/pool.c
index 0f989b16..bfef9704 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -275,6 +275,8 @@ pool_add_solvable_block(Pool *pool, int count)
Id nsolvables = pool->nsolvables;
if (!count)
return nsolvables;
+ if (count < 0 || count >= SOLV_MAX_BLKLEN)
+ solv_ovfl("solvable count overflow");
pool->solvables = solv_extend(pool->solvables, pool->nsolvables, count, sizeof(Solvable), SOLVABLE_BLOCK);
memset(pool->solvables + nsolvables, 0, sizeof(Solvable) * count);
pool->nsolvables += count;
diff --git a/src/repo.c b/src/repo.c
index b266d8d5..d6cd9747 100644
--- a/src/repo.c
+++ b/src/repo.c
@@ -48,7 +48,11 @@ repo_create(Pool *pool, const char *name)
pool->repos = (Repo **)solv_calloc(2, sizeof(Repo *));
}
else
- pool->repos = (Repo **)solv_realloc2(pool->repos, pool->nrepos + 1, sizeof(Repo *));
+ {
+ if (pool->nrepos + 1 >= SOLV_MAX_BLKLEN)
+ solv_ovfl("repository count overflow");
+ pool->repos = (Repo **)solv_realloc2(pool->repos, pool->nrepos + 1, sizeof(Repo *));
+ }
pool->repos[pool->nrepos] = repo;
pool->urepos++;
repo->repoid = pool->nrepos++;
@@ -619,6 +623,8 @@ solv_depmarker(Id keyname, Id marker)
Offset
repo_reserve_ids(Repo *repo, Offset olddeps, int num)
{
+ if (num < 0 || num >= SOLV_MAX_BLKLEN)
+ solv_ovfl("dependency array overflow");
num++; /* room for trailing ID_NULL */
if (!repo->idarraysize) /* ensure buffer space */
@@ -1352,6 +1358,8 @@ repo_add_repodata(Repo *repo, int flags)
}
else
{
+ if (repo->nrepodata + 1 >= SOLV_MAX_BLKLEN)
+ solv_ovfl("repodata count overflow");
repo->nrepodata++;
repo->repodata = solv_realloc2(repo->repodata, repo->nrepodata, sizeof(*data));
}
diff --git a/src/repo_solv.c b/src/repo_solv.c
index b8c981fa..f9156920 100644
--- a/src/repo_solv.c
+++ b/src/repo_solv.c
@@ -18,7 +18,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
-#include <limits.h>
#include "repo_solv.h"
#include "util.h"
@@ -119,6 +118,11 @@ read_id(Repodata *data, Id max)
data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_id: id too large (%u/%u)", x, max);
return 0;
}
+ else if (x >= 0x7fffffffU)
+ {
+ data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_id: id too large (%u)", x);
+ return 0;
+ }
return x;
}
x = (x << 7) ^ c ^ 128;
@@ -155,6 +159,11 @@ read_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end)
data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_idarray: id too large (%u/%u)", x, max);
return 0;
}
+ else if (x >= 0x7fffffffU)
+ {
+ data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_idarray: id too large (%u)", x);
+ return 0;
+ }
if (map)
x = map[x];
if (store == end)
@@ -924,8 +933,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags)
key = keys + i;
key->name = id;
key->type = type;
- key->size = read_id(&data, type == REPOKEY_TYPE_CONSTANTID ? numid + numrel : 0);
- key->storage = read_id(&data, 0);
+ key->size = read_id(&data, type == REPOKEY_TYPE_CONSTANTID ? numid + numrel : SOLV_MAX_BLKLEN);
+ key->storage = read_id(&data, SOLV_MAX_BLKLEN);
/* old versions used SOLVABLE for main solvable data */
if (key->storage != KEY_STORAGE_INCORE && key->storage != KEY_STORAGE_VERTICAL_OFFSET && key->storage != KEY_STORAGE_SOLVABLE && key->storage != KEY_STORAGE_IDARRAYBLOCK)
data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "unsupported storage type %d", key->storage);
@@ -977,7 +986,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags)
/******* Part 5: Schemata ********************************************/
- id = read_id(&data, 0);
+ id = read_id(&data, SOLV_MAX_BLKLEN);
schemadata = solv_calloc(id + 1, sizeof(Id));
schemadatap = schemadata + 1;
schemadataend = schemadatap + id;
@@ -1017,20 +1026,10 @@ repo_add_solv(Repo *repo, FILE *fp, int flags)
idarraydatap = idarraydataend = 0;
size_idarray = 0;
- maxsize = read_id(&data, 0);
- allsize = read_id(&data, 0);
- if (maxsize < 0 || allsize < 0)
- {
- data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "negative data size in solv header");
- id = 0;
- goto data_error;
- }
- if (maxsize > INT_MAX - 5)
- {
- data.error = pool_error(pool, SOLV_ERROR_OVERFLOW, "data size overflow in solv header");
- id = 0;
- goto data_error;
- }
+ maxsize = read_id(&data, SOLV_MAX_BLKLEN);
+ allsize = read_id(&data, SOLV_MAX_BLKLEN);
+ if (data.error)
+ goto data_error;
maxsize += 5; /* so we can read the next schema of an array */
if (maxsize > allsize)
maxsize = allsize;
@@ -1294,7 +1293,17 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key
id = keys[i].name;
if ((keys[i].type == REPOKEY_TYPE_IDARRAY || keys[i].type == REPOKEY_TYPE_REL_IDARRAY)
&& id >= INTERESTED_START && id <= INTERESTED_END)
- size_idarray += keys[i].size;
+ {
+ size_idarray += keys[i].size;
+ if ((unsigned int)size_idarray >= (unsigned int)SOLV_MAX_BLKLEN)
+ break;
+ }
+ }
+ if (i < numkeys)
+ {
+ data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "idarray size overflow");
+ size_idarray = 0;
+ break; /* overflow */
}
/* allocate needed space in repo */
/* we add maxsize because it is an upper limit for all idarrays, thus we can't overflow */
diff --git a/src/repodata.c b/src/repodata.c
index 10e7b42b..20493d4c 100644
--- a/src/repodata.c
+++ b/src/repodata.c
@@ -183,9 +183,10 @@ repodata_key2id(Repodata *data, Repokey *key, int create)
Id
repodata_schema2id(Repodata *data, Id *schema, int create)
{
- int h, len, i;
+ int h, i;
Id *sp, cid;
Id *schematahash;
+ size_t len;
if (!*schema)
return 0; /* XXX: allow empty schema? */
@@ -223,6 +224,8 @@ repodata_schema2id(Repodata *data, Id *schema, int create)
/* a new one */
if (!create)
return 0;
+ if (len >= SOLV_MAX_BLKLEN)
+ solv_ovfl("schema length overflow");
data->schemadata = solv_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
data->schemata = solv_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
/* add schema */
diff --git a/src/strpool.c b/src/strpool.c
index 0b95f0f7..98a9a07f 100644
--- a/src/strpool.c
+++ b/src/strpool.c
@@ -12,6 +12,8 @@
#define STRING_BLOCK 2047
#define STRINGSPACE_BLOCK 65535
+#define STRING_MAXSIZE 0x40000000
+
void
stringpool_init(Stringpool *ss, const char *strs[])
{
@@ -113,6 +115,12 @@ stringpool_strn2id(Stringpool *ss, const char *str, unsigned int len, int create
if (!len)
return STRID_EMPTY;
+ if (len >= STRING_MAXSIZE)
+ {
+ solv_ovfl("maximum string size overflow");
+ return 0;
+ }
+
hashmask = ss->stringhashmask;
/* expand hashtable if needed */
@@ -160,11 +168,18 @@ stringpool_strn2id(Stringpool *ss, const char *str, unsigned int len, int create
Id
stringpool_str2id(Stringpool *ss, const char *str, int create)
{
+ size_t len;
if (!str)
return STRID_NULL;
if (!*str)
return STRID_EMPTY;
- return stringpool_strn2id(ss, str, (unsigned int)strlen(str), create);
+ len = strlen(str);
+ if (len >= STRING_MAXSIZE)
+ {
+ solv_ovfl("maximum string size overflow");
+ return 0;
+ }
+ return stringpool_strn2id(ss, str, (unsigned int)len, create);
}
void
diff --git a/src/util.c b/src/util.c
index 72426e09..da3963c9 100644
--- a/src/util.c
+++ b/src/util.c
@@ -21,6 +21,14 @@
#include "util.h"
+void
+solv_ovfl(const char *str)
+{
+ fprintf(stderr, "%s\n", str);
+ abort();
+ exit(1);
+}
+
void
solv_oom(size_t num, size_t len)
{
@@ -103,6 +111,8 @@ solv_extend_realloc(void *old, size_t len, size_t size, size_t block)
len = nlen;
}
}
+ if (len >= SOLV_MAX_BLKLEN)
+ solv_ovfl("solv extend realloc overflow");
return solv_realloc2(old, len, size);
}
diff --git a/src/util.h b/src/util.h
index 9c2b8249..28ec523c 100644
--- a/src/util.h
+++ b/src/util.h
@@ -44,6 +44,11 @@ extern size_t solv_validutf8(const char *buf);
extern char *solv_latin1toutf8(const char *buf);
extern char *solv_replacebadutf8(const char *buf, int replchar);
+#ifdef LIBSOLV_INTERNAL
+#define SOLV_MAX_BLKLEN 0x7fff0000
+extern void solv_ovfl(const char *);
+#endif
+
static inline void *solv_extend(void *buf, size_t len, size_t nmemb, size_t size, size_t block)
{
--
2.55.0

View File

@ -0,0 +1,414 @@
From aa10f54529b9d8aed7422b5de3c06487c5ccef92 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Wed, 29 Apr 2026 11:00:24 +0200
Subject: [PATCH 2/3] Add some more guards
---
src/pool.c | 25 +++++++++++++++++++------
src/queue.c | 7 +++++++
src/repo.c | 8 +++++---
src/repo_solv.c | 24 ++++++++----------------
src/repodata.c | 30 +++++++++++++++++++++++-------
src/strpool.c | 2 ++
src/util.c | 2 +-
src/util.h | 4 +++-
8 files changed, 68 insertions(+), 34 deletions(-)
diff --git a/src/pool.c b/src/pool.c
index bfef9704..03f74bdb 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -275,7 +275,7 @@ pool_add_solvable_block(Pool *pool, int count)
Id nsolvables = pool->nsolvables;
if (!count)
return nsolvables;
- if (count < 0 || count >= SOLV_MAX_BLKLEN)
+ if (count < 0 || count >= SOLV_MAX_INDEX)
solv_ovfl("solvable count overflow");
pool->solvables = solv_extend(pool->solvables, pool->nsolvables, count, sizeof(Solvable), SOLVABLE_BLOCK);
memset(pool->solvables + nsolvables, 0, sizeof(Solvable) * count);
@@ -407,7 +407,7 @@ pool_shrink_whatprovides(Pool *pool)
return;
r = pool->whatprovidesdataoff - o;
pool->whatprovidesdataoff = o;
- pool->whatprovidesdata = solv_realloc(pool->whatprovidesdata, (o + pool->whatprovidesdataleft) * sizeof(Id));
+ pool->whatprovidesdata = solv_realloc2(pool->whatprovidesdata, o + pool->whatprovidesdataleft, sizeof(Id));
if (r > pool->whatprovidesdataleft)
r = pool->whatprovidesdataleft;
memset(pool->whatprovidesdata + o, 0, r * sizeof(Id));
@@ -436,7 +436,7 @@ pool_shrink_whatprovidesaux(Pool *pool)
*wp++ = id;
}
newoff = wp - pool->whatprovidesauxdata;
- pool->whatprovidesauxdata = solv_realloc(pool->whatprovidesauxdata, newoff * sizeof(Id));
+ pool->whatprovidesauxdata = solv_realloc2(pool->whatprovidesauxdata, newoff, sizeof(Id));
POOL_DEBUG(SOLV_DEBUG_STATS, "shrunk whatprovidesauxdata from %d to %d\n", pool->whatprovidesauxdataoff, newoff);
pool->whatprovidesauxdataoff = newoff;
}
@@ -505,6 +505,8 @@ pool_createwhatprovides(Pool *pool)
*idp = 1; /* offset for empty list */
continue;
}
+ if (n >= 0xffff0000U - off)
+ solv_ovfl("pool whatprovides overflow");
off += n; /* make space for all providers */
*idp = off++; /* now idp points to terminating zero */
np++; /* inc # of provider 'slots' for stats */
@@ -516,8 +518,12 @@ pool_createwhatprovides(Pool *pool)
extra = 2 * pool->nrels;
if (extra < 256)
extra = 256;
+ if (extra > 0x10000000)
+ extra = 0x10000000;
+ if (off > 0xffff0000U - extra)
+ solv_ovfl("pool whatprovides overflow");
- POOL_DEBUG(SOLV_DEBUG_STATS, "provide space needed: %d + %d\n", off, extra);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "provide space needed: %u + %d\n", off, extra);
/* alloc space for all providers + extra */
whatprovidesdata = solv_calloc(off + extra, sizeof(Id));
@@ -570,6 +576,9 @@ pool_createwhatprovides(Pool *pool)
pool->whatprovidesdataoff = off;
pool->whatprovidesdataleft = extra;
pool_shrink_whatprovides(pool);
+ if (pool->whatprovidesdataoff >= SOLV_MAX_INDEX || pool->whatprovidesdataoff + pool->whatprovidesdataleft >= SOLV_MAX_INDEX)
+ solv_ovfl("pool whatprovides overflow");
+
if (pool->whatprovidesaux)
pool_shrink_whatprovidesaux(pool);
POOL_DEBUG(SOLV_DEBUG_STATS, "whatprovides memory used: %d K id array, %d K data\n", (pool->ss.nstrings + pool->nrels + WHATPROVIDES_BLOCK) / (int)(1024/sizeof(Id)), (pool->whatprovidesdataoff + pool->whatprovidesdataleft) / (int)(1024/sizeof(Id)));
@@ -655,16 +664,20 @@ pool_ids2whatprovides(Pool *pool, Id *ids, int count)
{
Offset off;
- if (count == 0) /* queue empty -> 1 */
+ if (count <= 0) /* queue empty -> 1 */
return 1;
if (count == 1 && *ids == SYSTEMSOLVABLE)
return 2;
+ if (count >= SOLV_MAX_INDEX)
+ solv_ovfl("pool whatprovides data overflow");
/* extend whatprovidesdata if needed, +1 for 0-termination */
if (pool->whatprovidesdataleft < count + 1)
{
POOL_DEBUG(SOLV_DEBUG_STATS, "growing provides hash data...\n");
- pool->whatprovidesdata = solv_realloc(pool->whatprovidesdata, (pool->whatprovidesdataoff + count + 4096) * sizeof(Id));
+ if ((unsigned int)(SOLV_MAX_INDEX - pool->whatprovidesdataoff) < (unsigned int)count + 4096)
+ solv_ovfl("pool whatprovides data overflow");
+ pool->whatprovidesdata = solv_realloc2(pool->whatprovidesdata, pool->whatprovidesdataoff + count + 4096, sizeof(Id));
pool->whatprovidesdataleft = count + 4096;
}
diff --git a/src/queue.c b/src/queue.c
index 6d5e531d..d7133f42 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -16,6 +16,8 @@
#include "queue.h"
#include "util.h"
+#define SOLV_MAX_QUEUECOUNT SOLV_MAX_INDEX
+
static inline int
queue_extra_space(int size)
{
@@ -87,6 +89,8 @@ queue_alloc_one(Queue *q)
else
{
int extra_space = queue_extra_space(q->count);
+ if (q->count + extra_space >= SOLV_MAX_QUEUECOUNT)
+ solv_ovfl("queue count overflow");
if (!q->alloc)
{
q->alloc = solv_malloc2(q->count + extra_space, sizeof(Id));
@@ -210,6 +214,9 @@ queue_prealloc(Queue *q, int n)
queue_alloc_one(q);
off = q->elements - q->alloc;
extra_space = queue_extra_space(q->count + n);
+ if (n >= SOLV_MAX_QUEUECOUNT || (unsigned int)(off + q->count + n + extra_space) >= (unsigned int)SOLV_MAX_QUEUECOUNT)
+ solv_ovfl("queue count overflow");
+
q->alloc = solv_realloc2(q->alloc, off + q->count + n + extra_space, sizeof(Id));
q->elements = q->alloc + off;
q->left = n + extra_space;
diff --git a/src/repo.c b/src/repo.c
index d6cd9747..050ea24e 100644
--- a/src/repo.c
+++ b/src/repo.c
@@ -49,7 +49,7 @@ repo_create(Pool *pool, const char *name)
}
else
{
- if (pool->nrepos + 1 >= SOLV_MAX_BLKLEN)
+ if (pool->nrepos + 1 >= SOLV_MAX_INDEX)
solv_ovfl("repository count overflow");
pool->repos = (Repo **)solv_realloc2(pool->repos, pool->nrepos + 1, sizeof(Repo *));
}
@@ -623,7 +623,7 @@ solv_depmarker(Id keyname, Id marker)
Offset
repo_reserve_ids(Repo *repo, Offset olddeps, int num)
{
- if (num < 0 || num >= SOLV_MAX_BLKLEN)
+ if (num < 0 || num >= SOLV_MAX_INDEX)
solv_ovfl("dependency array overflow");
num++; /* room for trailing ID_NULL */
@@ -648,6 +648,8 @@ repo_reserve_ids(Repo *repo, Offset olddeps, int num)
for (idstart = idend = repo->idarraydata + olddeps; *idend++; ) /* find end */
;
+ if (idend - idstart >= SOLV_MAX_INDEX - (num + 1))
+ solv_ovfl("dependency array overflow");
count = idend - idstart - 1 + num; /* new size */
repo->idarraydata = solv_extend(repo->idarraydata, repo->idarraysize, count, sizeof(Id), IDARRAY_BLOCK);
@@ -1358,7 +1360,7 @@ repo_add_repodata(Repo *repo, int flags)
}
else
{
- if (repo->nrepodata + 1 >= SOLV_MAX_BLKLEN)
+ if (repo->nrepodata + 1 >= SOLV_MAX_INDEX)
solv_ovfl("repodata count overflow");
repo->nrepodata++;
repo->repodata = solv_realloc2(repo->repodata, repo->nrepodata, sizeof(*data));
diff --git a/src/repo_solv.c b/src/repo_solv.c
index f9156920..ca3fa213 100644
--- a/src/repo_solv.c
+++ b/src/repo_solv.c
@@ -118,11 +118,6 @@ read_id(Repodata *data, Id max)
data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_id: id too large (%u/%u)", x, max);
return 0;
}
- else if (x >= 0x7fffffffU)
- {
- data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_id: id too large (%u)", x);
- return 0;
- }
return x;
}
x = (x << 7) ^ c ^ 128;
@@ -159,11 +154,6 @@ read_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end)
data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_idarray: id too large (%u/%u)", x, max);
return 0;
}
- else if (x >= 0x7fffffffU)
- {
- data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_idarray: id too large (%u)", x);
- return 0;
- }
if (map)
x = map[x];
if (store == end)
@@ -858,6 +848,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags)
}
idmap[i + numid] = MAKERELDEP(id); /* fill Id map */
}
+ if ((unsigned int)pool->nrels >= (unsigned int)SOLV_MAX_INDEX)
+ solv_ovfl("relation count overflow");
pool_shrink_rels(pool); /* vacuum */
}
@@ -933,8 +925,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags)
key = keys + i;
key->name = id;
key->type = type;
- key->size = read_id(&data, type == REPOKEY_TYPE_CONSTANTID ? numid + numrel : SOLV_MAX_BLKLEN);
- key->storage = read_id(&data, SOLV_MAX_BLKLEN);
+ key->size = read_id(&data, type == REPOKEY_TYPE_CONSTANTID ? numid + numrel : type == REPOKEY_TYPE_CONSTANT ? 0 : SOLV_MAX_INDEX);
+ key->storage = read_id(&data, SOLV_MAX_INDEX);
/* old versions used SOLVABLE for main solvable data */
if (key->storage != KEY_STORAGE_INCORE && key->storage != KEY_STORAGE_VERTICAL_OFFSET && key->storage != KEY_STORAGE_SOLVABLE && key->storage != KEY_STORAGE_IDARRAYBLOCK)
data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "unsupported storage type %d", key->storage);
@@ -986,7 +978,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags)
/******* Part 5: Schemata ********************************************/
- id = read_id(&data, SOLV_MAX_BLKLEN);
+ id = read_id(&data, SOLV_MAX_INDEX);
schemadata = solv_calloc(id + 1, sizeof(Id));
schemadatap = schemadata + 1;
schemadataend = schemadatap + id;
@@ -1026,8 +1018,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags)
idarraydatap = idarraydataend = 0;
size_idarray = 0;
- maxsize = read_id(&data, SOLV_MAX_BLKLEN);
- allsize = read_id(&data, SOLV_MAX_BLKLEN);
+ maxsize = read_id(&data, SOLV_MAX_INDEX);
+ allsize = read_id(&data, SOLV_MAX_INDEX);
if (data.error)
goto data_error;
maxsize += 5; /* so we can read the next schema of an array */
@@ -1295,7 +1287,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key
&& id >= INTERESTED_START && id <= INTERESTED_END)
{
size_idarray += keys[i].size;
- if ((unsigned int)size_idarray >= (unsigned int)SOLV_MAX_BLKLEN)
+ if ((unsigned int)size_idarray >= (unsigned int)SOLV_MAX_INDEX)
break;
}
}
diff --git a/src/repodata.c b/src/repodata.c
index 20493d4c..f3ab4348 100644
--- a/src/repodata.c
+++ b/src/repodata.c
@@ -160,6 +160,8 @@ repodata_key2id(Repodata *data, Repokey *key, int create)
if (!create)
return 0;
/* allocate new key */
+ if (data->nkeys >= SOLV_MAX_INDEX)
+ solv_ovfl("repodata key overflow");
data->keys = solv_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
data->keys[data->nkeys++] = *key;
if (data->verticaloffset)
@@ -224,8 +226,8 @@ repodata_schema2id(Repodata *data, Id *schema, int create)
/* a new one */
if (!create)
return 0;
- if (len >= SOLV_MAX_BLKLEN)
- solv_ovfl("schema length overflow");
+ if (len >= SOLV_MAX_INDEX)
+ solv_ovfl("repodata schema length overflow");
data->schemadata = solv_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
data->schemata = solv_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
/* add schema */
@@ -314,6 +316,8 @@ repodata_str2dir(Repodata *data, const char *dir, int create)
while (*dir)
{
dire = strchrnul(dir, '/');
+ if (dire - dir >= (size_t)0x40000000)
+ solv_ovfl("repodata dir component size overflow");
if (data->localpool)
id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
else
@@ -2532,9 +2536,11 @@ void
repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
{
Repokey key;
- int l;
+ size_t l;
l = strlen(str) + 1;
+ if (l >= 0x40000000)
+ solv_ovfl("repodata string size overflow");
key.name = keyname;
key.type = REPOKEY_TYPE_STR;
key.size = 0;
@@ -2553,6 +2559,8 @@ repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
if (len < 0)
return;
+ if (len >= 0x40000000)
+ solv_ovfl("repodata binary size overflow");
key.name = keyname;
key.type = REPOKEY_TYPE_BINARY;
key.size = 0;
@@ -2697,9 +2705,11 @@ evrid2vrstr(Pool *pool, Id evrid)
}
static inline void
-repodata_set_poolstrn(Repodata *data, Id solvid, Id keyname, const char *str, int l)
+repodata_set_poolstrn(Repodata *data, Id solvid, Id keyname, const char *str, size_t l)
{
Id id;
+ if (l >= (size_t)0x40000000)
+ solv_ovfl("repodata poolstr size overflow");
if (data->localpool)
id = stringpool_strn2id(&data->spool, str, l, 1);
else
@@ -2708,7 +2718,7 @@ repodata_set_poolstrn(Repodata *data, Id solvid, Id keyname, const char *str, in
}
static inline void
-repodata_set_strn(Repodata *data, Id solvid, Id keyname, const char *str, int l)
+repodata_set_strn(Repodata *data, Id solvid, Id keyname, const char *str, size_t l)
{
if (!str[l])
repodata_set_str(data, solvid, keyname, str);
@@ -2727,7 +2737,7 @@ repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, c
Pool *pool = data->repo->pool;
Solvable *s;
const char *str, *fp;
- int l = 0;
+ size_t l = 0;
if (medianr)
repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
@@ -2867,6 +2877,8 @@ repodata_set_sourcepkg(Repodata *data, Id solvid, const char *sourcepkg)
repodata_set_str(data, solvid, SOLVABLE_SOURCENAME, sourcepkg);
return;
}
+ if (p - sourcepkg >= (size_t)0x40000000)
+ solv_ovfl("repodata sourcepkg size overflow");
p--;
while (p > sourcepkg && *p != '.')
p--;
@@ -2916,6 +2928,8 @@ repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
key.size = 0;
key.storage = KEY_STORAGE_INCORE;
repodata_set(data, solvid, &key, data->attriddatalen);
+ if (q->count + 1 >= SOLV_MAX_INDEX)
+ solv_ovfl("repodata idarray size overflow");
data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
for (i = 0; i < q->count; i++)
data->attriddata[data->attriddatalen++] = q->elements[i];
@@ -2940,10 +2954,12 @@ void
repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
{
Id stroff;
- int l;
+ size_t l;
assert(dir);
l = strlen(str) + 1;
+ if (l >= SOLV_MAX_INDEX)
+ solv_ovfl("repodata dirstr size overflow");
data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
memcpy(data->attrdata + data->attrdatalen, str, l);
stroff = data->attrdatalen;
diff --git a/src/strpool.c b/src/strpool.c
index 98a9a07f..8d7c1212 100644
--- a/src/strpool.c
+++ b/src/strpool.c
@@ -263,6 +263,8 @@ stringpool_integrate(Stringpool *ss, int numid, Offset sizeid, Id *idmap)
idmap[i] = id; /* repo relative -> pool relative */
sp += l; /* next string */
}
+ if ((unsigned int)ss->nstrings >= (unsigned int)SOLV_MAX_INDEX)
+ solv_ovfl("string count overpool");
stringpool_shrink(ss); /* vacuum */
return 1;
}
diff --git a/src/util.c b/src/util.c
index da3963c9..cfcd0d01 100644
--- a/src/util.c
+++ b/src/util.c
@@ -111,7 +111,7 @@ solv_extend_realloc(void *old, size_t len, size_t size, size_t block)
len = nlen;
}
}
- if (len >= SOLV_MAX_BLKLEN)
+ if (len >= SOLV_MAX_INDEX)
solv_ovfl("solv extend realloc overflow");
return solv_realloc2(old, len, size);
}
diff --git a/src/util.h b/src/util.h
index 28ec523c..15c694f1 100644
--- a/src/util.h
+++ b/src/util.h
@@ -45,7 +45,9 @@ extern char *solv_latin1toutf8(const char *buf);
extern char *solv_replacebadutf8(const char *buf, int replchar);
#ifdef LIBSOLV_INTERNAL
-#define SOLV_MAX_BLKLEN 0x7fff0000
+/* our index values are 32 bit signed integers. We use a bit less than the
+ * maximum value to allow for a bit of overshooting */
+#define SOLV_MAX_INDEX 0x7fff0000
extern void solv_ovfl(const char *);
#endif
--
2.55.0

View File

@ -0,0 +1,76 @@
From 0d38eb567a3f4b7c6c4898a502f7a505df588e88 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Tue, 19 May 2026 11:21:11 +0200
Subject: [PATCH 3/3] Add some guards to the tmpspace functions
I don't think this matters, but it's the right thing to do.
Also add pool_bin2hex to the size_t TODO list
---
src/pool.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/pool.c b/src/pool.c
index 03f74bdb..f3b80e5e 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -38,6 +38,8 @@
#include "knownid.h"
#undef KNOWNID_INITIALIZE
+#define POOL_MAX_TMPSPACE_LEN 0x1000000
+
/* create pool */
Pool *
pool_create(void)
@@ -1760,6 +1762,8 @@ pool_alloctmpspace(Pool *pool, int len)
int n = pool->tmpspace.n;
if (!len)
return 0;
+ if (len >= POOL_MAX_TMPSPACE_LEN)
+ solv_ovfl("tmpspace size overflow");
if (len > pool->tmpspace.len[n])
{
pool->tmpspace.buf[n] = solv_realloc(pool->tmpspace.buf[n], len + 32);
@@ -1809,11 +1813,13 @@ pool_freetmpspace(Pool *pool, const char *space)
char *
pool_tmpjoin(Pool *pool, const char *str1, const char *str2, const char *str3)
{
- int l1, l2, l3;
+ size_t l1, l2, l3;
char *s, *str;
l1 = str1 ? strlen(str1) : 0;
l2 = str2 ? strlen(str2) : 0;
l3 = str3 ? strlen(str3) : 0;
+ if (l1 >= POOL_MAX_TMPSPACE_LEN || l2 >= POOL_MAX_TMPSPACE_LEN || l3 >= POOL_MAX_TMPSPACE_LEN)
+ solv_ovfl("tmpspace size overflow");
s = str = pool_alloctmpspace(pool, l1 + l2 + l3 + 1);
if (l1)
{
@@ -1837,12 +1843,14 @@ pool_tmpjoin(Pool *pool, const char *str1, const char *str2, const char *str3)
char *
pool_tmpappend(Pool *pool, const char *str1, const char *str2, const char *str3)
{
- int l1, l2, l3;
+ size_t l1, l2, l3;
char *s, *str;
l1 = str1 ? strlen(str1) : 0;
l2 = str2 ? strlen(str2) : 0;
l3 = str3 ? strlen(str3) : 0;
+ if (l1 >= POOL_MAX_TMPSPACE_LEN || l2 >= POOL_MAX_TMPSPACE_LEN || l3 >= POOL_MAX_TMPSPACE_LEN)
+ solv_ovfl("tmpspace size overflow");
str = pool_alloctmpspace_free(pool, str1, l1 + l2 + l3 + 1);
if (str)
str1 = str;
@@ -1875,6 +1883,8 @@ pool_bin2hex(Pool *pool, const unsigned char *buf, int len)
char *s;
if (!len)
return "";
+ if (len >= POOL_MAX_TMPSPACE_LEN / 2)
+ solv_ovfl("pool_bin2hex size overflow");
s = pool_alloctmpspace(pool, 2 * len + 1);
solv_bin2hex(buf, len, s);
return s;
--
2.55.0

View File

@ -76,6 +76,14 @@ Patch3: 0004-Cope-with-integer-overflow-in-data-size-arithmetics-.patch
# <https://github.com/openSUSE/libsolv/pull/622>.
Patch4: 0005-Fix-a-buffer-overflow-when-decompressing-solv-pages.patch
# Add guards that abort if an overflow is about to happen
# https://github.com/openSUSE/libsolv/commit/37a47d24e81fd3c02b0fdc7f0dd440e95e9fe7ae
Patch6: 0006-Also-guard-against-block-size-overflows.patch
# https://github.com/openSUSE/libsolv/commit/aa100c8382200e72461b03c1f731e7e6c03bba24
Patch7: 0007-Add-some-more-guards.patch
# https://github.com/openSUSE/libsolv/commit/25dccfc54388f26b6b1196caa69647ffead05286
Patch8: 0008-Add-some-guards-to-the-tmpspace-functions.patch
BuildRequires: cmake >= 3.5
BuildRequires: gcc-c++
BuildRequires: ninja-build