From 4bf6638a6f69f9982f2a0bce73c62a4b9833d96c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 4 Jan 2018 16:32:03 +0100 Subject: [PATCH] Restrict capacity of plists to 2^28 resp. 2^60 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. --- src/plist.c | 5 +++++ src/plist.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/plist.c b/src/plist.c index 6fa3535663..aceb716137 100644 --- a/src/plist.c +++ b/src/plist.c @@ -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; } diff --git a/src/plist.h b/src/plist.h index 6dde4dcf1c..3de54464c6 100644 --- a/src/plist.h +++ b/src/plist.h @@ -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)); }