Skip to content

Commit

Permalink
Restrict capacity of plists to 2^28 resp. 2^60
Browse files Browse the repository at this point in the history
By adding bounds checks to GrowPlist and NEW_PLIST, we restrict the capacity
of plain lists to the maximum value of an immediate integer, i.e. 2^28 on a
32 bit system and 2^60 on a 64 bit system. The check in GrowPlist triggers
an error, as it can be triggered by the user. The check in NEW_PLIST is a
run-time assertion, and should never be triggered by user actions, only by
buggy kernel code.

This restriction fixes overflows and other problems, which can lead to
crashes, corrupt data or nonsense computations.

It poses no actual limitation in practice, for the following reasons:

First off, many other places already effectively limited the length of a
plist they can interact with to the maximum value of an immediate integer.
E.g. such limitations exist for sublist access via l{poss}, EmptyPlist(),
ASS_PLIST_DEFAULT, and more.

Secondly, with this change,  the effective size (in bytes) of a plist of this
maximal length would be 2^30 resp. 2^63. The latter certainly poses no actual
limitation. The former corresponds to 1 GB. While GAP in principle supports
slightly larger bags on 32 bit systems (the GASMAN heap can grow up to almost
4GB if the host system supports it),, there is not much you can do with GAP
if most of its heap is filled with a gigantic plist, so this restriction
seems acceptable.
  • Loading branch information
fingolfin authored and ChrisJefferson committed Jan 8, 2018
1 parent 6d3a478 commit 4bf6638
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/plist.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,13 @@ Int GrowPlist (
UInt plen; /* new physical length */
UInt good; /* good new physical length */

if (need > INT_INTOBJ_MAX)
ErrorMayQuit("GrowPlist: List size too large", 0, 0);

/* find out how large the plain list should become */
good = 5 * (SIZE_OBJ(list)/sizeof(Obj)-1) / 4 + 4;
if (good > INT_INTOBJ_MAX)
good = INT_INTOBJ_MAX;

/* but maybe we need more */
if ( need < good ) { plen = good; }
Expand Down
1 change: 1 addition & 0 deletions src/plist.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
static inline Obj NEW_PLIST(UInt type, Int plen)
{
GAP_ASSERT(plen >= 0);
GAP_ASSERT(plen <= INT_INTOBJ_MAX);
return NewBag(type, (plen + 1) * sizeof(Obj));
}

Expand Down

0 comments on commit 4bf6638

Please sign in to comment.