diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,10 @@
+### 0.21.2
+
++ Do not free `Ptr Word8` types after performing the call to C,
+since they only get passed along. Otherwise one could easily double free in functions such as [GdkPixbuf.pixbufNewFromData](https://hackage.haskell.org/package/gi-gdkpixbuf/docs/GI-GdkPixbuf-Objects-Pixbuf.html#v:pixbufNewFromData).
+
++ Fix a leak on optional `ScopeTypeAsync` callbacks.
+
 ### 0.20.4
 
 + Improve marshaling of array arguments with no specified size. This improves the generated bindings for various functions, for instance [`GObject.signalEmitv`](https://hackage.haskell.org/package/gi-gobject/docs/GI-GObject-Functions.html#v:signalEmitv).
diff --git a/haskell-gi.cabal b/haskell-gi.cabal
--- a/haskell-gi.cabal
+++ b/haskell-gi.cabal
@@ -1,5 +1,5 @@
 name:                haskell-gi
-version:             0.21.1
+version:             0.21.2
 synopsis:            Generate Haskell bindings for GObject Introspection capable libraries
 description:         Generate Haskell bindings for GObject Introspection capable libraries. This includes most notably
                      Gtk+, but many other libraries in the GObject ecosystem provide introspection data too.
diff --git a/lib/Data/GI/CodeGen/Callable.hs b/lib/Data/GI/CodeGen/Callable.hs
--- a/lib/Data/GI/CodeGen/Callable.hs
+++ b/lib/Data/GI/CodeGen/Callable.hs
@@ -333,20 +333,28 @@
               return (maker, wrapper, drop)
         _ -> terror $ "prepareInCallback : Not an interface! " <> T.pack (ppShow arg)
 
-  when (scope == ScopeTypeAsync) $ do
-   ft <- typeShow <$> foreignType (argType arg)
-   line $ ptrName <> " <- callocMem :: IO (Ptr (" <> ft <> "))"
-
   wrapMaybe arg >>= bool
             (do
               let name' = prime name
-                  p = if (scope == ScopeTypeAsync)
-                      then parenthesize $ "Just " <> ptrName
-                      else "Nothing"
                   dropped =
                       case drop of
                         Just dropper -> parenthesize (dropper <> " " <> name)
                         Nothing -> name
+              -- ScopeTypeAsync callbacks are somewhat tricky: they
+              -- will be called only once, and the data associated to
+              -- them will be invalid after the first call.
+              --
+              -- So we pass them a pointer to a dynamically allocated
+              -- `Ptr FunPtr`, which contains a pointer to the
+              -- `FunPtr` we dynamically allocate wrapping the Haskell
+              -- function. On first invocation, the wrapper will then
+              -- free this memory.
+              p <- if (scope == ScopeTypeAsync)
+                   then do ft <- typeShow <$> foreignType (argType arg)
+                           line $ ptrName <> " <- callocMem :: IO (Ptr (" <> ft <> "))"
+                           return $ parenthesize $ "Just " <> ptrName
+                   else return "Nothing"
+
               line $ name' <> " <- " <> maker <> " "
                        <> parenthesize (wrapper <> " " <> p <> " " <> dropped)
               when (scope == ScopeTypeAsync) $
@@ -361,14 +369,16 @@
                     jName' = prime jName
                 line $ "Just " <> jName <> " -> do"
                 indent $ do
-                         let p = if (scope == ScopeTypeAsync)
-                                 then parenthesize $ "Just " <> ptrName
-                                 else "Nothing"
-                             dropped =
-                                 case drop of
+                         let dropped = case drop of
                                    Just dropper ->
                                        parenthesize (dropper <> " " <> jName)
                                    Nothing -> jName
+                         p <- if (scope == ScopeTypeAsync)
+                           then do ft <- typeShow <$> foreignType (argType arg)
+                                   line $ ptrName <> " <- callocMem :: IO (Ptr (" <> ft <> "))"
+                                   return $ parenthesize $ "Just " <> ptrName
+                           else return "Nothing"
+
                          line $ jName' <> " <- " <> maker <> " "
                                   <> parenthesize (wrapper <> " "
                                                    <> p <> " " <> dropped)
diff --git a/lib/Data/GI/CodeGen/Transfer.hs b/lib/Data/GI/CodeGen/Transfer.hs
--- a/lib/Data/GI/CodeGen/Transfer.hs
+++ b/lib/Data/GI/CodeGen/Transfer.hs
@@ -30,6 +30,8 @@
 basicFreeFn (TBasicType TFileName) = Just "freeMem"
 basicFreeFn (TBasicType _) = Nothing
 basicFreeFn (TInterface _) = Nothing
+-- Just passed along
+basicFreeFn (TCArray False (-1) (-1) (TBasicType TUInt8)) = Nothing
 basicFreeFn (TCArray{}) = Just "freeMem"
 basicFreeFn (TGArray _) = Just "unrefGArray"
 basicFreeFn (TPtrArray _) = Just "unrefPtrArray"
@@ -93,6 +95,8 @@
                                  return Nothing
                           else return Nothing
     _ -> return Nothing
+-- Just passed along
+basicFreeFnOnError (TCArray False (-1) (-1) (TBasicType TUInt8)) _ = return Nothing
 basicFreeFnOnError (TCArray{}) _ = return $ Just "freeMem"
 basicFreeFnOnError (TGArray _) _ = return $ Just "unrefGArray"
 basicFreeFnOnError (TPtrArray _) _ = return $ Just "unrefPtrArray"
