Add guards that abort if an overflow is about to happen
Related: RHEL-128441
This commit is contained in:
parent
2fa3970fa7
commit
ff8b649c41
281
0006-Also-guard-against-block-size-overflows.patch
Normal file
281
0006-Also-guard-against-block-size-overflows.patch
Normal 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
|
||||
|
||||
414
0007-Add-some-more-guards.patch
Normal file
414
0007-Add-some-more-guards.patch
Normal 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
|
||||
|
||||
76
0008-Add-some-guards-to-the-tmpspace-functions.patch
Normal file
76
0008-Add-some-guards-to-the-tmpspace-functions.patch
Normal 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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user