git.iko.soy/typeable/pandoc
on master help sign in
Lua: always load built-in Lua scripts from default data-dir

The Lua modules `pandoc` and `pandoc.List` are now always loaded from the system's default data directory. Loading from a different directory by overriding the default path, e.g. via `--data-dir`, is no longer supported to avoid unexpected behavior and to address security concerns.

commit490065f3ed3dd9377a740ad6fcbc441a658889dd authorAlbert Krewinkel <albert@zeitkraut.de> dateTue 26 Jan 2021, 14:19 (6 years ago) parent3f9eee4
4 files changed+44−46
src/Text/Pandoc/Lua/Init.hs+14−4 src/Text/Pandoc/Lua/Module/Pandoc.hs+4−4 src/Text/Pandoc/Lua/Packages.hs+7−26 src/Text/Pandoc/Lua/PandocLua.hs+19−12
src/Text/Pandoc/Lua/Init.hs+14−4
@@ -12,17 +12,18 @@ module Text.Pandoc.Lua.Init
1212 ( runLua
1313 ) where
1414
15+import Control.Monad (when)
1516import Control.Monad.Catch (try)
1617import Control.Monad.Trans (MonadIO (..))
1718import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)
1819import Foreign.Lua (Lua)
1920import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
21+import Text.Pandoc.Class.PandocMonad (readDataFile)
2022import Text.Pandoc.Class.PandocIO (PandocIO)
2123import Text.Pandoc.Error (PandocError)
2224import Text.Pandoc.Lua.Packages (installPandocPackageSearcher)
23−import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua,
24− loadScriptFromDataDir, runPandocLua)
25−
25+import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua, runPandocLua)
26+import Text.Pandoc.Lua.Util (throwTopMessageAsError')
2627import qualified Foreign.Lua as Lua
2728import qualified Text.Pandoc.Definition as Pandoc
2829import qualified Text.Pandoc.Lua.Module.Pandoc as ModulePandoc
@@ -44,7 +45,7 @@ initLuaState = do
4445 liftPandocLua Lua.openlibs
4546 installPandocPackageSearcher
4647 initPandocModule
47− loadScriptFromDataDir "init.lua"
48+ loadInitScript "init.lua"
4849 where
4950 initPandocModule :: PandocLua ()
5051 initPandocModule = do
@@ -61,6 +62,15 @@ initLuaState = do
6162 -- assign module to global variable
6263 liftPandocLua $ Lua.setglobal "pandoc"
6364
65+ loadInitScript :: FilePath -> PandocLua ()
66+ loadInitScript scriptFile = do
67+ script <- readDataFile scriptFile
68+ status <- liftPandocLua $ Lua.dostring script
69+ when (status /= Lua.OK) . liftPandocLua $
70+ throwTopMessageAsError'
71+ (("Couldn't load '" ++ scriptFile ++ "'.\n") ++)
72+
73+
6474-- | AST elements are marshaled via normal constructor functions in the
6575-- @pandoc@ module. However, accessing Lua globals from Haskell is
6676-- expensive (due to error handling). Accessing the Lua registry is much
src/Text/Pandoc/Lua/Module/Pandoc.hs+4−4
@@ -25,7 +25,7 @@ import Text.Pandoc.Definition (Block, Inline)
2525import Text.Pandoc.Lua.Filter (walkInlines, walkBlocks, LuaFilter, SingletonsList (..))
2626import Text.Pandoc.Lua.Marshaling ()
2727import Text.Pandoc.Lua.PandocLua (PandocLua, addFunction, liftPandocLua,
28− loadScriptFromDataDir)
28+ loadDefaultModule)
2929import Text.Pandoc.Walk (Walkable)
3030import Text.Pandoc.Options (ReaderOptions (readerExtensions))
3131import Text.Pandoc.Process (pipeProcess)
@@ -38,11 +38,11 @@ import qualified Foreign.Lua as Lua
3838import qualified Text.Pandoc.Lua.Util as LuaUtil
3939import Text.Pandoc.Error
4040
41−-- | Push the "pandoc" on the lua stack. Requires the `list` module to be
42−-- loaded.
41+-- | Push the "pandoc" package to the Lua stack. Requires the `List`
42+-- module to be loadable.
4343pushModule :: PandocLua NumResults
4444pushModule = do
45− loadScriptFromDataDir "pandoc.lua"
45+ loadDefaultModule "pandoc"
4646 addFunction "read" readDoc
4747 addFunction "pipe" pipeFn
4848 addFunction "walk_block" walkBlock
src/Text/Pandoc/Lua/Packages.hs+7−26
@@ -1,6 +1,3 @@
1−{-# LANGUAGE FlexibleContexts #-}
2−{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
41{- |
52 Module : Text.Pandoc.Lua.Packages
63 Copyright : Copyright © 2017-2021 Albert Krewinkel
@@ -15,13 +12,9 @@ module Text.Pandoc.Lua.Packages
1512 ( installPandocPackageSearcher
1613 ) where
1714
18−import Control.Monad.Catch (try)
1915import Control.Monad (forM_)
20−import Data.ByteString (ByteString)
21−import Foreign.Lua (Lua, NumResults)
22−import Text.Pandoc.Error (PandocError)
23−import Text.Pandoc.Class.PandocMonad (readDataFile)
24−import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua)
16+import Foreign.Lua (NumResults)
17+import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua, loadDefaultModule)
2518
2619import qualified Foreign.Lua as Lua
2720import qualified Foreign.Lua.Module.Text as Text
@@ -54,24 +47,12 @@ pandocPackageSearcher pkgName =
5447 "pandoc.types" -> pushWrappedHsFun Types.pushModule
5548 "pandoc.utils" -> pushWrappedHsFun Utils.pushModule
5649 "text" -> pushWrappedHsFun Text.pushModule
57− _ -> searchPureLuaLoader
50+ "pandoc.List" -> pushWrappedHsFun (loadDefaultModule pkgName)
51+ _ -> reportPandocSearcherFailure
5852 where
5953 pushWrappedHsFun f = liftPandocLua $ do
6054 Lua.pushHaskellFunction f
6155 return 1
62− searchPureLuaLoader = do
63− let filename = pkgName ++ ".lua"
64− try (readDataFile filename) >>= \case
65− Right script -> pushWrappedHsFun (loadStringAsPackage pkgName script)
66− Left (_ :: PandocError) -> liftPandocLua $ do
67− Lua.push ("\n\tno file '" ++ filename ++ "' in pandoc's datadir")
68− return (1 :: NumResults)
69−
70−loadStringAsPackage :: String -> ByteString -> Lua NumResults
71−loadStringAsPackage pkgName script = do
72− status <- Lua.dostring script
73− if status == Lua.OK
74− then return (1 :: NumResults)
75− else do
76− msg <- Lua.popValue
77− Lua.raiseError ("Error while loading `" <> pkgName <> "`.\n" <> msg)
56+ reportPandocSearcherFailure = liftPandocLua $ do
57+ Lua.push ("\n\t" <> pkgName <> "is not one of pandoc's default packages")
58+ return (1 :: NumResults)
src/Text/Pandoc/Lua/PandocLua.hs+19−12
@@ -23,24 +23,23 @@ module Text.Pandoc.Lua.PandocLua
2323 , runPandocLua
2424 , liftPandocLua
2525 , addFunction
26− , loadScriptFromDataDir
26+ , loadDefaultModule
2727 ) where
2828
29−import Control.Monad (when)
3029import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)
3130import Control.Monad.Except (MonadError (catchError, throwError))
3231import Control.Monad.IO.Class (MonadIO (liftIO))
3332import Foreign.Lua (Lua (..), NumResults, Pushable, ToHaskellFunction)
3433import Text.Pandoc.Class.PandocIO (PandocIO)
35−import Text.Pandoc.Class.PandocMonad (PandocMonad (..), readDataFile)
36−import Text.Pandoc.Error (PandocError)
34+import Text.Pandoc.Class.PandocMonad (PandocMonad (..), readDefaultDataFile)
35+import Text.Pandoc.Error (PandocError (PandocLuaError))
3736import Text.Pandoc.Lua.Global (Global (..), setGlobals)
3837import Text.Pandoc.Lua.ErrorConversion (errorConversion)
3938
4039import qualified Control.Monad.Catch as Catch
40+import qualified Data.Text as T
4141import qualified Foreign.Lua as Lua
4242import qualified Text.Pandoc.Class.IO as IO
43−import qualified Text.Pandoc.Lua.Util as LuaUtil
4443
4544-- | Type providing access to both, pandoc and Lua operations.
4645newtype PandocLua a = PandocLua { unPandocLua :: Lua a }
@@ -86,14 +85,22 @@ addFunction name fn = liftPandocLua $ do
8685 Lua.pushHaskellFunction fn
8786 Lua.rawset (-3)
8887
89−-- | Load a file from pandoc's data directory.
90−loadScriptFromDataDir :: FilePath -> PandocLua ()
91−loadScriptFromDataDir scriptFile = do
92− script <- readDataFile scriptFile
88+-- | Load a pure Lua module included with pandoc. Leaves the result on
89+-- the stack and returns @NumResults 1@.
90+--
91+-- The script is loaded from the default data directory. We do not load
92+-- from data directories supplied via command line, as this could cause
93+-- scripts to be executed even though they had not been passed explicitly.
94+loadDefaultModule :: String -> PandocLua NumResults
95+loadDefaultModule name = do
96+ script <- readDefaultDataFile (name <> ".lua")
9397 status <- liftPandocLua $ Lua.dostring script
94− when (status /= Lua.OK) . liftPandocLua $
95− LuaUtil.throwTopMessageAsError'
96− (("Couldn't load '" ++ scriptFile ++ "'.\n") ++)
98+ if status == Lua.OK
99+ then return (1 :: NumResults)
100+ else do
101+ msg <- liftPandocLua Lua.popValue
102+ let err = "Error while loading `" <> name <> "`.\n" <> msg
103+ throwError $ PandocLuaError (T.pack err)
97104
98105-- | Global variables which should always be set.
99106defaultGlobals :: PandocIO [Global]