Skip to content

Commit

Permalink
Stop users reassigning '~'
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisJefferson committed Jan 6, 2017
1 parent d1f2050 commit f1ce770
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 16 deletions.
8 changes: 4 additions & 4 deletions src/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -2610,13 +2610,13 @@ CVar CompListTildeExpr (
list = CompListExpr1( expr );

/* assign the list to '~' */
Emit( "AssGVar( Tilde, %c );\n", list );
Emit( "AssGVarUnsafe( Tilde, %c );\n", list );

/* evaluate the subexpressions into the list value */
CompListExpr2( list, expr );

/* restore old value of '~' */
Emit( "AssGVar( Tilde, %c );\n", tilde );
Emit( "AssGVarUnsafe( Tilde, %c );\n", tilde );
if ( IS_TEMP_CVAR( tilde ) ) FreeTemp( TEMP_CVAR( tilde ) );

/* return the list value */
Expand Down Expand Up @@ -2828,13 +2828,13 @@ CVar CompRecTildeExpr (
rec = CompRecExpr1( expr );

/* assign the record value to the variable '~' */
Emit( "AssGVar( Tilde, %c );\n", rec );
Emit( "AssGVarUnsafe( Tilde, %c );\n", rec );

/* evaluate the subexpressions into the record value */
CompRecExpr2( rec, expr );

/* restore the old value of '~' */
Emit( "AssGVar( Tilde, %c );\n", tilde );
Emit( "AssGVarUnsafe( Tilde, %c );\n", tilde );
if ( IS_TEMP_CVAR( tilde ) ) FreeTemp( TEMP_CVAR( tilde ) );

/* return the record value */
Expand Down
8 changes: 4 additions & 4 deletions src/exprs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,13 +1087,13 @@ Obj EvalListTildeExpr (
list = ListExpr1( expr );

/* assign the list to '~' */
AssGVar( Tilde, list );
AssGVarUnsafe( Tilde, list );

/* evaluate the subexpressions into the list value */
ListExpr2( list, expr );

/* restore old value of '~' */
AssGVar( Tilde, tilde );
AssGVarUnsafe( Tilde, tilde );

/* return the list value */
return list;
Expand Down Expand Up @@ -1441,13 +1441,13 @@ Obj EvalRecTildeExpr (
rec = RecExpr1( expr );

/* assign the record value to the variable '~' */
AssGVar( Tilde, rec );
AssGVarUnsafe( Tilde, rec );

/* evaluate the subexpressions into the record value */
RecExpr2( rec, expr );

/* restore the old value of '~' */
AssGVar( Tilde, tilde );
AssGVarUnsafe( Tilde, tilde );

/* return the record value */
return rec;
Expand Down
39 changes: 35 additions & 4 deletions src/gvars.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,29 @@ Obj ErrorMustHaveAssObjHandler (

static Obj REREADING; /* Copy of GAP global variable REREADING */

/****************************************************************************
**
** AssGVarUnsafe(<gvar>,<val>)
**
** Assign to a global variable with no safety checks
** - Does not check if the variable is readonly
** - Does not check if it is automatic, has internal copies or fopies
**
** The current main use of this function is to handle the `~` variable,
** both for speed and because it is marked read-only to avoid users editing
** it.
*/

void AssGVarUnsafe (
UInt gvar,
Obj val )
{
/* assign the value to the global variable */
VAL_GVAR(gvar) = val;
CHANGED_BAG( ValGVars );

}

void AssGVar (
UInt gvar,
Obj val )
Expand All @@ -186,10 +209,16 @@ void AssGVar (
/* make certain that the variable is not read only */
while ( (REREADING != True) &&
(ELM_PLIST( WriteGVars, gvar ) == INTOBJ_INT(0)) ) {
ErrorReturnVoid(
"Variable: '%s' is read only",
(Int)CSTR_STRING( ELM_PLIST(NameGVars,gvar) ), 0L,
"you can 'return;' after making it writable" );

if(gvar == Tilde) {
ErrorMayQuit("'~' cannot be assigned",0L,0L);
}
else {
ErrorReturnVoid(
"Variable: '%s' is read only",
(Int)CSTR_STRING( ELM_PLIST(NameGVars,gvar) ), 0L,
"you can 'return;' after making it writable" );
}
}

/* assign the value to the global variable */
Expand Down Expand Up @@ -1134,6 +1163,8 @@ static Int PostRestore (
/* create the global variable '~' */
Tilde = GVarName( "~" );

/* stop unauthorised changes to '~' */
MakeReadOnlyGVar(Tilde);

/* update fopies and copies */
UpdateCopyFopyInfo();
Expand Down
11 changes: 11 additions & 0 deletions src/gvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ extern void AssGVar (
Obj val );


/****************************************************************************
**
*F AssGVarUnsafe(<gvar>,<val>) . . assign to a global variable with checks
**
** 'AssGVarUnsafe' assigns the value <val> to the global variable <gvar>
** without readonly checks or copie/fopie checking.
*/
extern void AssGVarUnsafe (
UInt gvar,
Obj val );

/****************************************************************************
**
*F ValAutoGVar(<gvar>) . . . . . . . . value of a automatic global variable
Expand Down
8 changes: 4 additions & 4 deletions src/intrprtr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2325,7 +2325,7 @@ void IntrListExprBegin (
old = VAL_GVAR( Tilde );
if ( old != 0 ) { PushObj( old ); }
else { PushVoidObj(); }
AssGVar( Tilde, list );
AssGVarUnsafe( Tilde, list );
}

/* push the list */
Expand Down Expand Up @@ -2398,7 +2398,7 @@ void IntrListExprEnd (
if ( top ) {
list = PopObj();
old = PopVoidObj();
AssGVar( Tilde, old );
AssGVarUnsafe( Tilde, old );
PushObj( list );
}

Expand Down Expand Up @@ -2538,7 +2538,7 @@ void IntrRecExprBegin (
old = VAL_GVAR( Tilde );
if ( old != 0 ) { PushObj( old ); }
else { PushVoidObj(); }
AssGVar( Tilde, record );
AssGVarUnsafe( Tilde, record );
}

/* push the record */
Expand Down Expand Up @@ -2621,7 +2621,7 @@ void IntrRecExprEnd (
if ( top ) {
record = PopObj();
old = PopVoidObj();
AssGVar( Tilde, old );
AssGVarUnsafe( Tilde, old );
PushObj( record );
}
}
Expand Down
28 changes: 28 additions & 0 deletions tst/testinstall/tilde.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
gap> START_TEST("tilde.tst");
gap> aqq~ := 1;
Error, Variable: 'aqq' must have a value
Syntax error: ; expected in stream:1
aqq~ := 1;
^
gap> ~a := 1;
Error, Variable: '~' must have a value
Syntax error: ; expected in stream:1
~a := 1;
^
gap> ~ := 1;
Error, '~' cannot be assigned
gap> l := [2, ~];
[ 2, ~ ]
gap> l = l[2];
true
gap> r := rec(x := ~, y := [1,2,~]);
rec( x := ~, y := [ 1, 2, ~ ] )
gap> r.x;
rec( x := ~, y := [ 1, 2, ~ ] )
gap> r.y;
[ 1, 2, rec( x := ~[3], y := ~ ) ]
gap> r.x;
rec( x := ~, y := [ 1, 2, ~ ] )
gap> r.y[3];
rec( x := ~, y := [ 1, 2, ~ ] )
gap> STOP_TEST( "tilde.tst", 1);

0 comments on commit f1ce770

Please sign in to comment.