Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restrict capacity of plists to 2^28 resp. 2^60 (revision of #2039) #2064

Merged
merged 3 commits into from
Jan 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/memusage.gi
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ InstallGlobalFunction( MemoryUsage, function( o )
continue;
fi;

mem := mem + SHALLOW_SIZE(o) + MU_MemBagHeader + MU_MemPointer;
mem := mem + SIZE_OBJ(o) + MU_MemBagHeader + MU_MemPointer;
if IsRat(o) then
visit(NumeratorRat(o));
visit(DenominatorRat(o));
Expand Down
14 changes: 13 additions & 1 deletion lib/obsolete.gd
Original file line number Diff line number Diff line change
Expand Up @@ -592,5 +592,17 @@ DeclareObsoleteSynonym( "RecFields", "RecNames" );

#############################################################################
##
#E
#F SHALLOW_SIZE
##
## 'SHALLOW_SIZE' is an alias for the kernel function 'SIZE_OBJ'. Note that
## in the past, SIZE_OBJ was buggy for immediate inputs (i.e. small integers
## or finite field elements), hence packages using either of these
## UNDOCUMENTED kernel functions may wish to keep using SHALLOW_SIZE until
## they can adjust their minimal GAP version requirements.
##
## still used by cvec, datastructures, orb, recog
DeclareObsoleteSynonym( "SHALLOW_SIZE", "SIZE_OBJ" );

#############################################################################
##
#E
2 changes: 1 addition & 1 deletion src/code.c
Original file line number Diff line number Diff line change
Expand Up @@ -1517,7 +1517,7 @@ void CodeAInv ( void )
Int i;

expr = PopExpr();
if ( IS_INTEXPR(expr) && INT_INTEXPR(expr) != -(1L<<NR_SMALL_INT_BITS) ) {
if ( IS_INTEXPR(expr) && INT_INTEXPR(expr) != INT_INTOBJ_MIN ) {
i = INT_INTEXPR(expr);
PushExpr( INTEXPR_INT( -i ) );
}
Expand Down
7 changes: 3 additions & 4 deletions src/cyclotom.c
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ Obj Cyclotomic (
for ( i = 0; i < n; i += p ) {
cof = res[(i+n/p)%n];
if ( ! IS_INTOBJ(cof)
|| (cof == INTOBJ_INT(-(1L<<NR_SMALL_INT_BITS))) ) {
|| (cof == INTOBJ_MIN) ) {
CHANGED_BAG( ResultCyc );
cof = DIFF( INTOBJ_INT(0), cof );
res = BASE_PTR_PLIST(ResultCyc);
Expand Down Expand Up @@ -813,7 +813,7 @@ static UInt FindCommonField(UInt nl, UInt nr, UInt *ml, UInt *mr)
/* Compute the result (lcm) in 64 bit */
n8 = (UInt8)nl * ((UInt8)*ml);
/* Check if it is too large for a small int */
if (n8 > ((UInt8)(1) << NR_SMALL_INT_BITS))
if (n8 > INT_INTOBJ_MAX)
ErrorMayQuit("This computation would require a cyclotomic field too large to be handled",0L, 0L);

/* Switch to UInt now we know we can*/
Expand Down Expand Up @@ -1000,8 +1000,7 @@ Obj AInvCyc (
cfp = COEFS_CYC(res);
exp = EXPOS_CYC(res,len);
for ( i = 1; i < len; i++ ) {
if ( ! IS_INTOBJ( cfs[i] ) ||
cfs[i] == INTOBJ_INT(-(1L<<NR_SMALL_INT_BITS)) ) {
if ( ! IS_INTOBJ( cfs[i] ) || cfs[i] == INTOBJ_MIN ) {
CHANGED_BAG( res );
prd = AINV( cfs[i] );
cfs = CONST_COEFS_CYC(op);
Expand Down
41 changes: 17 additions & 24 deletions src/gap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1844,7 +1844,6 @@ Obj FuncGASMAN_STATS(Obj self)
{
Obj res;
Obj row;
Obj entry;
UInt i,j;
Int x;
res = NEW_PLIST(T_PLIST_TAB_RECT + IMMUTABLE, 2);
Expand All @@ -1858,15 +1857,7 @@ Obj FuncGASMAN_STATS(Obj self)
for (j = 1; j <= 8; j++)
{
x = SyGasmanNumbers[i-1][j];

/* convert x to GAP integer. x may be too big to be a small int */
if (x < (1L << NR_SMALL_INT_BITS))
entry = INTOBJ_INT(x);
else
entry = SUM( PROD(INTOBJ_INT(x >> (NR_SMALL_INT_BITS/2)),
INTOBJ_INT(1 << (NR_SMALL_INT_BITS/2))),
INTOBJ_INT( x % ( 1 << (NR_SMALL_INT_BITS/2))));
SET_ELM_PLIST(row, j, entry);
SET_ELM_PLIST(row, j, ObjInt_Int(x));
}
SET_ELM_PLIST(row, 9, INTOBJ_INT(SyGasmanNumbers[i-1][0]));
}
Expand All @@ -1891,25 +1882,27 @@ Obj FuncGASMAN_LIMITS( Obj self )

/****************************************************************************
**
*F FuncSHALLOW_SIZE( <self>, <obj> ) . . . . expert function 'SHALLOW_SIZE'
*F FuncTotalMemoryAllocated( <self> ) .expert function 'TotalMemoryAllocated'
*/
Obj FuncSHALLOW_SIZE (
Obj self,
Obj obj )

Obj FuncTotalMemoryAllocated( Obj self )
{
if (IS_INTOBJ(obj) || IS_FFE(obj))
return INTOBJ_INT(0);
else
return ObjInt_UInt( SIZE_BAG( obj ) );
return ObjInt_UInt8(SizeAllBags);
}

/****************************************************************************
**
*F FuncTotalMemoryAllocated( <self> ) .expert function 'TotalMemoryAllocated'
*F FuncSIZE_OBJ( <self>, <obj> ) . . . . expert function 'SIZE_OBJ'
**
** 'SIZE_OBJ( <obj> )' returns 0 for immediate objects, and otherwise
** returns the bag size of the object. This does not include the size of
** sub-objects.
*/

Obj FuncTotalMemoryAllocated( Obj self ) {
return ObjInt_UInt8(SizeAllBags);
Obj FuncSIZE_OBJ(Obj self, Obj obj)
{
if (IS_INTOBJ(obj) || IS_FFE(obj))
return INTOBJ_INT(0);
return ObjInt_UInt(SIZE_OBJ(obj));
}

/****************************************************************************
Expand Down Expand Up @@ -2022,7 +2015,7 @@ Obj FuncFUNC_BODY_SIZE(Obj self, Obj f)
if (TNUM_OBJ(f) != T_FUNCTION) return Fail;
body = BODY_FUNC(f);
if (body == 0) return INTOBJ_INT(0);
else return INTOBJ_INT( SIZE_BAG( body ) );
else return ObjInt_UInt( SIZE_BAG( body ) );
}

/****************************************************************************
Expand Down Expand Up @@ -2810,8 +2803,8 @@ static StructGVarFunc GVarFuncs [] = {
GVAR_FUNC(GASMAN_STATS, 0, ""),
GVAR_FUNC(GASMAN_MESSAGE_STATUS, 0, ""),
GVAR_FUNC(GASMAN_LIMITS, 0, ""),
GVAR_FUNC(SHALLOW_SIZE, 1, "object"),
GVAR_FUNC(TotalMemoryAllocated, 0, ""),
GVAR_FUNC(SIZE_OBJ, 1, "object"),
GVAR_FUNC(TNUM_OBJ, 1, "object"),
GVAR_FUNC(TNAM_OBJ, 1, "object"),
GVAR_FUNC(OBJ_HANDLE, 1, "object"),
Expand Down
70 changes: 32 additions & 38 deletions src/integer.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,8 @@ Obj GMP_REDUCE( Obj gmp )
return gmp;
}
if ( SIZE_INT(gmp) == 1) {
if ( ( VAL_LIMB0(gmp) < ((1L<<NR_SMALL_INT_BITS)) ) ||
( IS_INTNEG(gmp) &&
( VAL_LIMB0(gmp) == (1L<<NR_SMALL_INT_BITS) ) ) ) {
if ( ( VAL_LIMB0(gmp) <= INT_INTOBJ_MAX ) ||
( IS_INTNEG(gmp) && VAL_LIMB0(gmp) == -INT_INTOBJ_MIN ) ) {
if ( IS_INTNEG(gmp) ) {
return INTOBJ_INT( -(Int)VAL_LIMB0(gmp) );
}
Expand Down Expand Up @@ -470,9 +469,8 @@ int IS_NORMALIZED_AND_REDUCED( Obj op, const char *func, int line )
Pr("WARNING: non-normalized gmp value (%s:%d)\n",(Int)func,line);
}
if ( SIZE_INT(op) == 1) {
if ( ( VAL_LIMB0(op) < ((1L<<NR_SMALL_INT_BITS)) ) ||
( IS_INTNEG(op) &&
( VAL_LIMB0(op) == (1L<<NR_SMALL_INT_BITS) ) ) ) {
if ( ( VAL_LIMB0(op) <= INT_INTOBJ_MAX ) ||
( IS_INTNEG(op) && VAL_LIMB0(op) == -INT_INTOBJ_MIN ) ) {
if ( IS_INTNEG(op) ) {
Pr("WARNING: non-reduced negative gmp value (%s:%d)\n",(Int)func,line);
return 0;
Expand All @@ -499,7 +497,7 @@ Obj ObjInt_Int( Int i )
{
Obj gmp;

if ( (-(1L<<NR_SMALL_INT_BITS) <= i) && (i < 1L<<NR_SMALL_INT_BITS )) {
if (INT_INTOBJ_MIN <= i && i <= INT_INTOBJ_MAX) {
return INTOBJ_INT(i);
}
else if (i < 0 ) {
Expand All @@ -516,9 +514,7 @@ Obj ObjInt_Int( Int i )
Obj ObjInt_UInt( UInt i )
{
Obj gmp;
UInt bound = 1UL << NR_SMALL_INT_BITS;

if (i < bound) {
if (i <= INT_INTOBJ_MAX) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is relying on how C handles signed / unsigned comparisons. I can't remember his they come out, and would have a small preference for assigning INT_INTOBJ_MAX to a UInt, just in case future people worry.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I briefly thought about adding an UINT_INTOBJ_MAX, but the C standard is pretty clear on this, and always has been. In a (simplified) nutshell, a signed and unsigned value are compared by casting the signed value to unsigned, which is always what we want for these bounds checks.

In short, INT_INTOBJ_MAX and UINT_INTOBJ_MAX would always do exactly the same thing, except when accidentally using UINT_INTOBJ_MAX to bound check a signed quantity... As such, UINT_INTOBJ_MAX could be misused by accident. I don't see a way to misuse INT_INTOBJ_MAX by accident.

return INTOBJ_INT(i);
}
else {
Expand All @@ -532,9 +528,9 @@ Obj ObjInt_UInt( UInt i )
Obj ObjInt_UIntInv( UInt i )
{
Obj gmp;
UInt bound = 1UL << NR_SMALL_INT_BITS;

if (i <= bound) {
// we need INT_INTOBJ_MIN <= -i; to express this with unsigned values, we
// must evaluate all negative terms, which leads to this equivalent check:
if (i <= -INT_INTOBJ_MIN) {
return INTOBJ_INT(-i);
}
else {
Expand Down Expand Up @@ -1287,9 +1283,9 @@ Obj AInvInt ( Obj gmp )
if ( IS_INTOBJ( gmp ) ) {

/* special case (ugh) */
if ( gmp == INTOBJ_INT( -(1L<<NR_SMALL_INT_BITS) ) ) {
if ( gmp == INTOBJ_MIN ) {
inv = NewBag( T_INTPOS, sizeof(mp_limb_t) );
SET_VAL_LIMB0( inv, 1L<<NR_SMALL_INT_BITS );
SET_VAL_LIMB0( inv, -INT_INTOBJ_MIN );
}

/* general case */
Expand All @@ -1302,9 +1298,8 @@ Obj AInvInt ( Obj gmp )
else {
if ( IS_INTPOS(gmp) ) {
/* special case */
if ( ( SIZE_INT(gmp) == 1 )
&& ( VAL_LIMB0(gmp) == (1L<<NR_SMALL_INT_BITS) ) ) {
return INTOBJ_INT( -(Int) (1L<<NR_SMALL_INT_BITS) );
if ( SIZE_INT(gmp) == 1 && VAL_LIMB0(gmp) == -INT_INTOBJ_MIN ) {
return INTOBJ_MIN;
}
else {
inv = NewBag( T_INTNEG, SIZE_OBJ(gmp) );
Expand Down Expand Up @@ -1334,9 +1329,9 @@ Obj AbsInt( Obj op )
if ( IS_INTOBJ(op) ) {
if ( ((Int)op) > 0 ) /* non-negative? */
return op;
else if ( op == INTOBJ_INT(-(1L << NR_SMALL_INT_BITS)) ) {
else if ( op == INTOBJ_MIN ) {
a = NewBag( T_INTPOS, sizeof(mp_limb_t) );
SET_VAL_LIMB0( a, (1L << NR_SMALL_INT_BITS) );
SET_VAL_LIMB0( a, -INT_INTOBJ_MIN );
return a;
} else
return (Obj)( 2 - (Int)op );
Expand Down Expand Up @@ -1515,15 +1510,15 @@ Obj ProdIntObj ( Obj n, Obj op )
/* <res> = 0 means that <res> is the neutral element */
else if ( IS_INTOBJ(n) && INT_INTOBJ(n) > 1 ) {
res = 0;
k = 1L << (NR_SMALL_INT_BITS+1);
k = 1L << NR_SMALL_INT_BITS;
l = INT_INTOBJ(n);
while ( 1 < k ) {
while ( 0 < k ) {
res = (res == 0 ? res : SUM( res, res ));
k = k / 2;
if ( k <= l ) {
res = (res == 0 ? op : SUM( res, op ));
l = l - k;
}
k = k / 2;
}
}

Expand Down Expand Up @@ -1683,15 +1678,15 @@ Obj PowObjInt ( Obj op, Obj n )
/* <res> = 0 means that <res> is the neutral element */
else if ( IS_INTOBJ(n) && INT_INTOBJ(n) > 0 ) {
res = 0;
k = 1L << (NR_SMALL_INT_BITS+1);
k = 1L << NR_SMALL_INT_BITS;
l = INT_INTOBJ(n);
while ( 1 < k ) {
while ( 0 < k ) {
res = (res == 0 ? res : PROD( res, res ));
k = k / 2;
if ( k <= l ) {
res = (res == 0 ? op : PROD( res, op ));
l = l - k;
}
k = k / 2;
}
}

Expand Down Expand Up @@ -1775,10 +1770,10 @@ Obj ModInt ( Obj opL, Obj opR )
else if ( IS_INTOBJ(opL) ) {

/* the small int -(1<<28) mod the large int (1<<28) is 0 */
if ( opL == INTOBJ_INT(-(Int)(1L<<NR_SMALL_INT_BITS) )
if ( opL == INTOBJ_MIN
&& ( IS_INTPOS(opR) )
&& ( SIZE_INT(opR) == 1 )
&& ( VAL_LIMB0(opR) == (mp_limb_t)(1L<<NR_SMALL_INT_BITS) ) )
&& ( VAL_LIMB0(opR) == -INT_INTOBJ_MIN ) )
mod = INTOBJ_INT(0);

/* in all other cases the remainder is equal the left operand */
Expand All @@ -1797,13 +1792,13 @@ Obj ModInt ( Obj opL, Obj opR )
i = INT_INTOBJ(opR); if ( i < 0 ) i = -i;

/* check whether right operand is a small power of 2 */
if ( i <= (1L<<NR_SMALL_INT_BITS) && !(i & (i-1)) ) {
if ( !(i & (i-1)) ) {
c = VAL_LIMB0(opL) & (i-1);
}

/* otherwise use the gmp function to divide */
else {
c = mpn_mod_1( CONST_ADDR_INT(opL), SIZE_INT(opL), (mp_limb_t)i );
c = mpn_mod_1( CONST_ADDR_INT(opL), SIZE_INT(opL), i );
}

/* now c is the result, it has the same sign as the left operand */
Expand Down Expand Up @@ -1906,10 +1901,9 @@ Obj QuoInt ( Obj opL, Obj opR )
if ( ARE_INTOBJS( opL, opR ) ) {

/* the small int -(1<<28) divided by -1 is the large int (1<<28) */
if ( opL == INTOBJ_INT(-(Int)(1L<<NR_SMALL_INT_BITS))
&& opR == INTOBJ_INT(-1) ) {
if ( opL == INTOBJ_MIN && opR == INTOBJ_INT(-1) ) {
quo = NewBag( T_INTPOS, sizeof(mp_limb_t) );
SET_VAL_LIMB0( quo, 1L<<NR_SMALL_INT_BITS );
SET_VAL_LIMB0( quo, -INT_INTOBJ_MIN );
return quo;
}

Expand All @@ -1930,9 +1924,9 @@ Obj QuoInt ( Obj opL, Obj opR )
else if ( IS_INTOBJ(opL) ) {

/* the small int -(1<<28) divided by the large int (1<<28) is -1 */
if ( opL == INTOBJ_INT(-(Int)(1L<<NR_SMALL_INT_BITS))
if ( opL == INTOBJ_MIN
&& IS_INTPOS(opR) && SIZE_INT(opR) == 1
&& VAL_LIMB0(opR) == 1L<<NR_SMALL_INT_BITS )
&& VAL_LIMB0(opR) == -INT_INTOBJ_MIN )
quo = INTOBJ_INT(-1);

/* in all other cases the quotient is of course zero */
Expand Down Expand Up @@ -2060,9 +2054,9 @@ Obj RemInt ( Obj opL, Obj opR )
else if ( IS_INTOBJ(opL) ) {

/* the small int -(1<<28) rem the large int (1<<28) is 0 */
if ( opL == INTOBJ_INT(-(Int)(1L<<NR_SMALL_INT_BITS))
if ( opL == INTOBJ_MIN
&& IS_INTPOS(opR) && SIZE_INT(opR) == 1
&& VAL_LIMB0(opR) == 1L<<NR_SMALL_INT_BITS )
&& VAL_LIMB0(opR) == -INT_INTOBJ_MIN )
rem = INTOBJ_INT(0);

/* in all other cases the remainder is equal the left operand */
Expand All @@ -2077,7 +2071,7 @@ Obj RemInt ( Obj opL, Obj opR )
i = INT_INTOBJ(opR); if ( i < 0 ) i = -i;

/* check whether right operand is a small power of 2 */
if ( i <= (1L<<NR_SMALL_INT_BITS) && !(i & (i-1)) ) {
if ( !(i & (i-1)) ) {
c = VAL_LIMB0(opL) & (i-1);
}

Expand Down
16 changes: 0 additions & 16 deletions src/intfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,6 @@
#include <src/stringobj.h>


/****************************************************************************
**
*F FuncSIZE_OBJ(<self>,<obj>)
**
** 'SIZE_OBJ( <obj> )' returns the size of a nonimmediate object. It can be
** used to debug memory use.
*/
Obj FuncSIZE_OBJ (
Obj self,
Obj a)
{
return INTOBJ_INT(SIZE_OBJ(a));
}


/****************************************************************************
**
** * * * * * * * "Mersenne twister" random numbers * * * * * * * * * * * * *
Expand Down Expand Up @@ -727,7 +712,6 @@ static StructGVarFunc GVarFuncs [] = {


GVAR_FUNC(HASHKEY_BAG, 4, "obj, int,int,int"),
GVAR_FUNC(SIZE_OBJ, 1, "obj"),
GVAR_FUNC(InitRandomMT, 1, "initstr"),
GVAR_FUNC(MAKE_BITFIELDS, -1, "widths"),
GVAR_FUNC(BUILD_BITFIELDS, -2, "widths, vals"),
Expand Down
Loading