commit f3397e43664392aa0f116f5de422b74fb820e3a3
parent e85307c7a13fc3348f0c0f3ab690186c60eaeaea
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 29 Jul 2026 11:06:16 +0200
fix integer underflow/overflow issues
Diffstat:
1 file changed, 30 insertions(+), 15 deletions(-)
diff --git a/src/main/extractor_datasource.c b/src/main/extractor_datasource.c
@@ -355,12 +355,13 @@ bfds_seek (struct BufferedFileDataSource *bfds,
LOG ("Invalid seek operation\n");
return -1;
}
- if (bfds->fsize < -pos)
+ /* -pos is undefined for INT64_MIN; negate in unsigned arithmetic. */
+ if (bfds->fsize < (uint64_t) -(uint64_t) pos)
{
LOG ("Invalid seek operation\n");
return -1;
}
- pos = bfds->fsize + pos;
+ pos = (int64_t) (bfds->fsize + (uint64_t) pos);
/* fall-through! */
case SEEK_SET:
if (pos < 0)
@@ -1052,19 +1053,33 @@ cfs_seek (struct CompressedFileSource *cfs,
switch (whence)
{
case SEEK_CUR:
- if (cfs->fpos + position < 0)
+ if (position < 0)
{
- /* underflow */
- LOG ("Invalid seek operation\n");
- return -1;
+ /* underflow; -position is undefined for INT64_MIN, so the
+ magnitude is taken in unsigned arithmetic */
+ if ((uint64_t) cfs->fpos < (uint64_t) -(uint64_t) position)
+ {
+ LOG ("Invalid seek operation\n");
+ return -1;
+ }
}
- if ( (-1 != cfs->uncompressed_size) &&
- (cfs->fpos + position > cfs->uncompressed_size) )
+ else
{
- LOG ("Invalid seek operation\n");
- return -1;
+ /* the addition itself must not overflow, which it can whenever
+ the uncompressed size is still unknown */
+ if (position > INT64_MAX - cfs->fpos)
+ {
+ LOG ("Invalid seek operation\n");
+ return -1;
+ }
+ if ( (-1 != cfs->uncompressed_size) &&
+ (cfs->fpos + position > cfs->uncompressed_size) )
+ {
+ LOG ("Invalid seek operation\n");
+ return -1;
+ }
}
- nposition = cfs->fpos + position;
+ nposition = (uint64_t) (cfs->fpos + position);
break;
case SEEK_END:
ASSERT (-1 != cfs->uncompressed_size);
@@ -1073,12 +1088,12 @@ cfs_seek (struct CompressedFileSource *cfs,
LOG ("Invalid seek operation\n");
return -1;
}
- if (cfs->uncompressed_size < -position)
+ if ((uint64_t) cfs->uncompressed_size < (uint64_t) -(uint64_t) position)
{
LOG ("Invalid seek operation\n");
return -1;
}
- nposition = cfs->uncompressed_size + position;
+ nposition = (uint64_t) (cfs->uncompressed_size + position);
break;
case SEEK_SET:
if (position < 0)
@@ -1098,10 +1113,10 @@ cfs_seek (struct CompressedFileSource *cfs,
LOG ("Invalid seek operation\n");
return -1;
}
- delta = nposition - cfs->fpos;
+ delta = (int64_t) (nposition - (uint64_t) cfs->fpos);
if (delta < 0)
{
- if (cfs->result_pos >= -delta)
+ if ((uint64_t) cfs->result_pos >= (uint64_t) -(uint64_t) delta)
{
cfs->result_pos += delta;
cfs->fpos += delta;