diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## Stache 2.3.4
+* Support GHC 9.6 thanks to @ysangkok
+* Fix infinite loop caused by unclosed sections thanks to @ernius
+
 ## Stache 2.3.3
 
 * Allow `vector-0.13`
diff --git a/Text/Mustache/Compile.hs b/Text/Mustache/Compile.hs
--- a/Text/Mustache/Compile.hs
+++ b/Text/Mustache/Compile.hs
@@ -50,7 +50,7 @@
 --
 -- > compileMustacheDir = complieMustacheDir' isMustacheFile
 compileMustacheDir ::
-  MonadIO m =>
+  (MonadIO m) =>
   -- | Which template to select after compiling
   PName ->
   -- | Directory with templates
@@ -64,7 +64,7 @@
 --
 -- @since 1.2.0
 compileMustacheDir' ::
-  MonadIO m =>
+  (MonadIO m) =>
   -- | Template selection predicate
   (FilePath -> Bool) ->
   -- | Which template to select after compiling
@@ -87,7 +87,7 @@
 --
 -- @since 0.2.2
 getMustacheFilesInDir ::
-  MonadIO m =>
+  (MonadIO m) =>
   -- | Directory with templates
   FilePath ->
   m [FilePath]
@@ -98,7 +98,7 @@
 --
 -- @since 1.2.0
 getMustacheFilesInDir' ::
-  MonadIO m =>
+  (MonadIO m) =>
   -- | Mustache file selection predicate
   (FilePath -> Bool) ->
   -- | Directory with templates
@@ -123,7 +123,7 @@
 -- The action can throw 'MustacheParserException' and the same exceptions as
 -- 'T.readFile'.
 compileMustacheFile ::
-  MonadIO m =>
+  (MonadIO m) =>
   -- | Location of the file
   FilePath ->
   m Template
@@ -134,8 +134,8 @@
     pname = pathToPName path
     compile = fmap (Template pname . M.singleton pname) . parseMustache path
 
--- | Compile a Mustache template from a lazy 'Text' value. The cache will
--- contain only this template named according to given 'PName'.
+-- | Compile a Mustache template from a 'Text' value. The cache will contain
+-- only this template named according to given 'PName'.
 compileMustacheText ::
   -- | How to name the template?
   PName ->
diff --git a/Text/Mustache/Parser.hs b/Text/Mustache/Parser.hs
--- a/Text/Mustache/Parser.hs
+++ b/Text/Mustache/Parser.hs
@@ -57,14 +57,19 @@
         Just <$> pUnescapedVariable,
         Just <$> pUnescapedSpecial,
         Just <$> pEscapedVariable,
-        Just <$> pTextBlock
+        Just <$> pTextBlock,
+        Just <$> pEmptyLnTextBlock
       ]
 {-# INLINE pMustache #-}
 
+pEmptyLnTextBlock :: Parser Node
+pEmptyLnTextBlock = TextBlock <$> eol'
+{-# INLINE pEmptyLnTextBlock #-}
+
 pTextBlock :: Parser Node
 pTextBlock = do
   start <- gets openingDel
-  txt <- fmap T.concat . many $ do
+  txt <- fmap T.concat . some $ do
     (void . notFollowedBy . string) start
     let textChar x = x /= T.head start && x /= '\n'
     string (T.take 1 start) <|> takeWhile1P (Just "text char") textChar
diff --git a/Text/Mustache/Type.hs b/Text/Mustache/Type.hs
--- a/Text/Mustache/Type.hs
+++ b/Text/Mustache/Type.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
@@ -66,12 +65,7 @@
 -- | @since 2.1.0
 instance TH.Lift Template where
   lift = liftData
-
-#if MIN_VERSION_template_haskell(2,17,0)
   liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
-#elif MIN_VERSION_template_haskell(2,16,0)
-  liftTyped = TH.unsafeTExpCoerce . TH.lift
-#endif
 
 -- | A structural element of a template.
 data Node
@@ -92,12 +86,7 @@
 -- | @since 2.1.0
 instance TH.Lift Node where
   lift = liftData
-
-#if MIN_VERSION_template_haskell(2,17,0)
   liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
-#elif MIN_VERSION_template_haskell(2,16,0)
-  liftTyped = TH.unsafeTExpCoerce . TH.lift
-#endif
 
 -- | Identifier for values to interpolate.
 --
@@ -114,12 +103,7 @@
 -- | @since 2.1.0
 instance TH.Lift Key where
   lift = liftData
-
-#if MIN_VERSION_template_haskell(2,17,0)
   liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
-#elif MIN_VERSION_template_haskell(2,16,0)
-  liftTyped = TH.unsafeTExpCoerce . TH.lift
-#endif
 
 -- | Pretty-print a key. This is helpful, for example, if you want to
 -- display an error message.
@@ -142,12 +126,7 @@
 -- | @since 2.1.0
 instance TH.Lift PName where
   lift = liftData
-
-#if MIN_VERSION_template_haskell(2,17,0)
   liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
-#elif MIN_VERSION_template_haskell(2,16,0)
-  liftTyped = TH.unsafeTExpCoerce . TH.lift
-#endif
 
 -- | Exception that is thrown when parsing of a template fails or referenced
 -- values are not provided.
@@ -187,20 +166,8 @@
 ----------------------------------------------------------------------------
 -- TH lifting helpers
 
-liftData
-
-#if MIN_VERSION_template_haskell(2,17,0)
-  :: (Data a, TH.Quote m) => a -> m TH.Exp
-#else
-  :: Data a => a -> TH.Q TH.Exp
-#endif
+liftData :: (Data a, TH.Quote m) => a -> m TH.Exp
 liftData = TH.dataToExpQ (fmap liftText . cast)
 
-liftText
-
-#if MIN_VERSION_template_haskell(2,17,0)
-  :: TH.Quote m => Text -> m TH.Exp
-#else
-  :: Text -> TH.Q TH.Exp
-#endif
+liftText :: (TH.Quote m) => Text -> m TH.Exp
 liftText t = TH.AppE (TH.VarE 'T.pack) <$> TH.lift (T.unpack t)
diff --git a/stache.cabal b/stache.cabal
--- a/stache.cabal
+++ b/stache.cabal
@@ -1,11 +1,11 @@
 cabal-version:   2.4
 name:            stache
-version:         2.3.3
+version:         2.3.4
 license:         MIT
 license-file:    LICENSE
 maintainer:      Mark Karpov <markkarpov92@gmail.com>
 author:          Mark Karpov <markkarpov92@gmail.com>
-tested-with:     ghc ==8.10.7 ghc ==9.0.2 ghc ==9.2.1
+tested-with:     ghc ==9.0.2 ghc ==9.2.8 ghc ==9.4.5 ghc ==9.6.2
 homepage:        https://github.com/stackbuilders/stache
 bug-reports:     https://github.com/stackbuilders/stache/issues
 synopsis:        Mustache templates for Haskell
@@ -44,7 +44,7 @@
     default-language: Haskell2010
     build-depends:
         aeson >=2 && <3,
-        base >=4.13 && <5.0,
+        base >=4.15 && <5.0,
         bytestring >=0.10 && <0.12,
         containers >=0.5 && <0.7,
         deepseq >=1.4 && <1.5,
@@ -52,7 +52,7 @@
         filepath >=1.2 && <1.5,
         megaparsec >=7.0 && <10.0,
         mtl >=2.1 && <3.0,
-        template-haskell >=2.11 && <2.19,
+        template-haskell >=2.11 && <2.21,
         text >=1.2 && <2.1,
         vector >=0.11 && <0.14
 
@@ -75,9 +75,9 @@
     default-language: Haskell2010
     build-depends:
         aeson >=2 && <3,
-        base >=4.13 && <5.0,
+        base >=4.15 && <5.0,
         gitrev >=1.3 && <1.4,
-        optparse-applicative >=0.14 && <0.18,
+        optparse-applicative >=0.14 && <0.19,
         stache,
         text >=0.2 && <2.1,
         yaml >=0.8 && <0.12,
@@ -105,13 +105,13 @@
     default-language:   Haskell2010
     build-depends:
         aeson >=2 && <3,
-        base >=4.13 && <5.0,
+        base >=4.15 && <5.0,
         containers >=0.5 && <0.7,
         hspec >=2.0 && <3.0,
         hspec-megaparsec >=2.0 && <3.0,
         megaparsec >=7.0 && <10.0,
         stache,
-        template-haskell >=2.11 && <2.19,
+        template-haskell >=2.11 && <2.21,
         text >=1.2 && <2.1
 
     if flag(dev)
@@ -127,7 +127,7 @@
     default-language: Haskell2010
     build-depends:
         aeson >=2 && <3,
-        base >=4.13 && <5.0,
+        base >=4.15 && <5.0,
         bytestring >=0.10 && <0.12,
         containers >=0.5 && <0.7,
         file-embed,
@@ -150,8 +150,8 @@
     default-language: Haskell2010
     build-depends:
         aeson >=2 && <3,
-        base >=4.13 && <5.0,
-        criterion >=0.6.2.1 && <1.6,
+        base >=4.15 && <5.0,
+        criterion >=0.6.2.1 && <1.7,
         deepseq >=1.4 && <1.5,
         megaparsec >=7.0 && <10.0,
         stache,
diff --git a/tests/Text/Mustache/ParserSpec.hs b/tests/Text/Mustache/ParserSpec.hs
--- a/tests/Text/Mustache/ParserSpec.hs
+++ b/tests/Text/Mustache/ParserSpec.hs
@@ -98,3 +98,5 @@
     it "rejects il-formed expressions" $ do
       let s = "{{ foo..bar }}"
       p s `shouldFailWith` err 7 (utoks "." <> elabel keyConstErr)
+    it "rejects unclosed sections" $
+      p `shouldFailOn` "{{#foo}} bar "
