Skip to content

Commit

Permalink
Disallow circular WAIF references
Browse files Browse the repository at this point in the history
WAIFs containing circular references can cause a space leak in the
database file if the cyclic references are not broken before the WAIFs
are garbage collected. Since LambdaMOO does not allow WAIFs to contain
circular references, we'll disallow them for now as well.
  • Loading branch information
verement committed Mar 27, 2016
1 parent a8ca50e commit af65e25
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 10 deletions.
8 changes: 0 additions & 8 deletions DIFFERENCES.md
Expand Up @@ -161,11 +161,3 @@ differences compared with LambdaMOO:

* EtaMOO defines the variable `WAIF` within MOO verbs to have the same value
as `typeof(new_waif())`.

* Currently EtaMOO allows WAIFs to contain circular references. While this
is by itself not a problem, it can cause a space leak in the database file
if the cyclic references are not broken before the WAIFs are garbage
collected. Note that LambdaMOO does not allow WAIFs to contain circular
references, so exporting a database with such references and loading it
into LambdaMOO may result in undefined behavior. (This is basically a bug
and subject to change.)
1 change: 0 additions & 1 deletion TODO
Expand Up @@ -33,7 +33,6 @@
** Enhance version number with git commit info
** Unicode strings in database file
** User reconnecting to different listening points
** Circular WAIF references
** Deepen value_bytes(waif)

* Before v1.0
Expand Down
16 changes: 15 additions & 1 deletion src/MOO/WAIF.hs
Expand Up @@ -26,7 +26,7 @@ import Data.IntMap (IntMap)
import Data.Monoid ((<>))
import Data.Typeable (Typeable)
import Database.VCache (PVar, VRef, VCacheable(put, get), VTx, VSpace,
unsafePVarAddr, deref, vref, vref',
unsafePVarAddr, deref, deref', vref, vref',
pvar_space, newPVar, readPVar, modifyPVar)

import qualified Data.HashMap.Lazy as HM
Expand All @@ -38,6 +38,7 @@ import MOO.Task
import MOO.Types
import MOO.Util

import qualified MOO.List as Lst
import qualified MOO.String as Str

type PropertyMap = VHashMap StrT (VRef Value)
Expand Down Expand Up @@ -148,6 +149,9 @@ storeWaifProperty waif name value = do
prop <- waifProperty name =<< waifClassObject waif
unless (propertyPermW prop) $ checkPermission (waifPropertyOwner waif prop)

-- disallow circular references
checkCyclic waif value

let var = waifData waif :: PVar PropertyMap
vspace = pvar_space var :: VSpace

Expand All @@ -156,6 +160,16 @@ storeWaifProperty waif name value = do

return value

checkCyclic :: WAIF -> Value -> MOO ()
checkCyclic waif = checkCyclic'
where checkCyclic' value = case value of
Lst x -> Lst.forM_ x checkCyclic'
Waf x | x == waif -> raise E_RECMOVE
| otherwise ->
mapM_ (checkCyclic' . deref') . HM.elems . unVHashMap =<<
liftVTx (readPVar $ waifData x)
_ -> return ()

callWaifVerb :: Value -> WAIF -> StrT -> [Value] -> MOO Value
callWaifVerb this waif name = callVerb this (waifClass waif) (prefix <> name)

Expand Down

0 comments on commit af65e25

Please sign in to comment.