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

Reset directory on failed file interpretation #1770

Merged
merged 7 commits into from
Dec 22, 2022
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
5 changes: 5 additions & 0 deletions intTests/test_directory_reset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Test that a failed `include` leaves the current working directory, as printed by
`:pwd`, unchanged. Do this by `include`ing a bogus file outside the current
directory, bracketed with calls to `:pwd`, making sure that those calls produce
identical output, and that that output is the same as the initial working
directory.
1 change: 1 addition & 0 deletions intTests/test_directory_reset/err/err.saw
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
this file probably won't parse
11 changes: 11 additions & 0 deletions intTests/test_directory_reset/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash

set -e

HERE=`pwd`
RES=`printf '%s\n%s\n%s\n' ':pwd' 'include "err/err.saw"' ':pwd' | \
$SAW --interactive --no-color | \
sed -r '/^\s*$/d' | \
sort | \
uniq -d`
[[ "$RES" =~ .*"$HERE"$.* ]]
22 changes: 10 additions & 12 deletions src/SAWScript/Interpreter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -390,13 +390,17 @@ interpretStmt printBinds stmt =
putTopLevelRW $ addTypedef (getVal name) ty rw

interpretFile :: FilePath -> Bool {- ^ run main? -} -> TopLevel ()
interpretFile file runMain = do
opts <- getOptions
stmts <- io $ SAWScript.Import.loadFile opts file
mapM_ stmtWithPrint stmts
when runMain interpretMain
writeVerificationSummary
interpretFile file runMain =
bracketTopLevel (io getCurrentDirectory) (io . setCurrentDirectory) (const interp)
where
interp =
do opts <- getOptions
io $ setCurrentDirectory (takeDirectory file)
stmts <- io $ SAWScript.Import.loadFile opts file
mapM_ stmtWithPrint stmts
when runMain interpretMain
writeVerificationSummary

stmtWithPrint s = do let withPos str = unlines $
("[output] at " ++ show (SS.getPos s) ++ ": ") :
map (\l -> "\t" ++ l) (lines str)
Expand Down Expand Up @@ -520,12 +524,9 @@ processFile proxy opts file mbSubshell mbProofSubshell = do
let ro'' = case mbProofSubshell of
Nothing -> ro'
Just m -> ro'{ roProofSubshell = m }
oldpath <- getCurrentDirectory
file' <- canonicalizePath file
setCurrentDirectory (takeDirectory file')
_ <- runTopLevel (interpretFile file' True) ro'' rw
`X.catch` (handleException opts)
setCurrentDirectory oldpath
return ()

-- Primitives ------------------------------------------------------------------
Expand Down Expand Up @@ -711,11 +712,8 @@ set_crucible_timeout t = do

include_value :: FilePath -> TopLevel ()
include_value file = do
oldpath <- io $ getCurrentDirectory
file' <- io $ canonicalizePath file
io $ setCurrentDirectory (takeDirectory file')
interpretFile file' False
io $ setCurrentDirectory oldpath

set_ascii :: Bool -> TopLevel ()
set_ascii b = do
Expand Down
12 changes: 11 additions & 1 deletion src/SAWScript/Value.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import Control.Applicative (Applicative)
#endif
import Control.Lens
import Control.Monad.Fail (MonadFail(..))
import Control.Monad.Catch (MonadThrow(..), MonadCatch(..), catches, Handler(..))
import Control.Monad.Catch (MonadThrow(..), MonadCatch(..), catches, Handler(..), try)
import Control.Monad.Except (ExceptT(..), runExceptT, MonadError(..))
import Control.Monad.Reader (MonadReader)
import qualified Control.Exception as X
Expand Down Expand Up @@ -562,6 +562,16 @@ runTopLevel :: IsValue a => TopLevel a -> TopLevelRO -> TopLevelRW -> IO (Value,
runTopLevel (TopLevel_ m) ro rw =
runStateContT (runReaderT m ro) (\a s -> return (toValue a,s)) rw

-- | A version of 'Control.Exception.bracket' specialized to 'TopLevel'. We
-- can't use 'Control.Monad.Catch.bracket' because it requires 'TopLevel' to
-- implement 'Control.Monad.Catch.MonadMask', which it can't do.
bracketTopLevel :: TopLevel a -> (a -> TopLevel b) -> (a -> TopLevel c) -> TopLevel c
bracketTopLevel acquire release action =
do resource <- acquire
try (action resource) >>= \case
Left (bad :: X.SomeException) -> release resource >> throwM bad
Right good -> release resource >> pure good

instance MonadIO TopLevel where
liftIO = io

Expand Down