From 4e632511433f2eef3959f05e76edfa2a8ca37cac Mon Sep 17 00:00:00 2001 From: Oleg Grenrus Date: Sat, 29 Jul 2023 21:19:03 +0300 Subject: [PATCH 1/2] Remove all unsafe FFI imports See https://github.com/haskellari/postgresql-libpq/pull/19 libpq can callback into Haskell, or do IO, so it's safer to just not use unsafe. The overhead should be minimal. --- src/Database/PostgreSQL/LibPQ/FFI.hs | 100 +++++++++++++-------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/Database/PostgreSQL/LibPQ/FFI.hs b/src/Database/PostgreSQL/LibPQ/FFI.hs index ef7924c..0693a59 100644 --- a/src/Database/PostgreSQL/LibPQ/FFI.hs +++ b/src/Database/PostgreSQL/LibPQ/FFI.hs @@ -35,53 +35,53 @@ foreign import capi "hs-libpq.h PQconnectStart" foreign import capi "hs-libpq.h PQconnectPoll" c_PQconnectPoll :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQdb" +foreign import capi "hs-libpq.h PQdb" c_PQdb :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQuser" +foreign import capi "hs-libpq.h PQuser" c_PQuser :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQpass" +foreign import capi "hs-libpq.h PQpass" c_PQpass :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQhost" +foreign import capi "hs-libpq.h PQhost" c_PQhost :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQport" +foreign import capi "hs-libpq.h PQport" c_PQport :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQoptions" +foreign import capi "hs-libpq.h PQoptions" c_PQoptions :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQbackendPID" +foreign import capi "hs-libpq.h PQbackendPID" c_PQbackendPID :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQconnectionNeedsPassword" +foreign import capi "hs-libpq.h PQconnectionNeedsPassword" c_PQconnectionNeedsPassword :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQconnectionUsedPassword" +foreign import capi "hs-libpq.h PQconnectionUsedPassword" c_PQconnectionUsedPassword :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQstatus" +foreign import capi "hs-libpq.h PQstatus" c_PQstatus :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQtransactionStatus" +foreign import capi "hs-libpq.h PQtransactionStatus" c_PQtransactionStatus :: Ptr PGconn -> IO CInt -- TODO: GHC #22043 foreign import ccall "hs-libpq.h PQparameterStatus" c_PQparameterStatus :: Ptr PGconn -> CString -> IO CString -foreign import capi unsafe "hs-libpq.h PQprotocolVersion" +foreign import capi "hs-libpq.h PQprotocolVersion" c_PQprotocolVersion :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQserverVersion" +foreign import capi "hs-libpq.h PQserverVersion" c_PQserverVersion :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQlibVersion" +foreign import capi "hs-libpq.h PQlibVersion" c_PQlibVersion :: IO CInt -foreign import capi unsafe "hs-libpq.h PQsocket" +foreign import capi "hs-libpq.h PQsocket" c_PQsocket :: Ptr PGconn -> IO CInt foreign import capi "hs-libpq.h PQerrorMessage" @@ -99,7 +99,7 @@ foreign import capi "hs-libpq.h PQresetStart" foreign import capi "hs-libpq.h PQresetPoll" c_PQresetPoll :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQclientEncoding" +foreign import capi "hs-libpq.h PQclientEncoding" c_PQclientEncoding :: Ptr PGconn -> IO CInt -- TODO: GHC #22043 @@ -110,7 +110,7 @@ foreign import capi "hs-libpq.h PQsetClientEncoding" c_PQsetClientEncoding :: Ptr PGconn -> CString -> IO CInt type PGVerbosity = CInt -foreign import capi unsafe "hs-libpq.h PQsetErrorVerbosity" +foreign import capi "hs-libpq.h PQsetErrorVerbosity" c_PQsetErrorVerbosity :: Ptr PGconn -> PGVerbosity -> IO PGVerbosity foreign import capi "hs-libpq.h PQputCopyData" @@ -159,22 +159,22 @@ foreign import capi "hs-libpq.h &PQfreeCancel" foreign import capi "hs-libpq.h PQcancel" c_PQcancel :: Ptr PGcancel -> CString -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQnotifies" +foreign import capi "hs-libpq.h PQnotifies" c_PQnotifies :: Ptr PGconn -> IO (Ptr Notify) foreign import capi "hs-libpq.h PQconsumeInput" c_PQconsumeInput :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQisBusy" +foreign import capi "hs-libpq.h PQisBusy" c_PQisBusy :: Ptr PGconn -> IO CInt foreign import capi "hs-libpq.h PQsetnonblocking" c_PQsetnonblocking :: Ptr PGconn -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQisnonblocking" +foreign import capi "hs-libpq.h PQisnonblocking" c_PQisnonblocking :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQsetSingleRowMode" +foreign import capi "hs-libpq.h PQsetSingleRowMode" c_PQsetSingleRowMode :: Ptr PGconn -> IO CInt foreign import capi "hs-libpq.h PQgetResult" @@ -207,67 +207,67 @@ foreign import capi "hs-libpq.h PQdescribePortal" foreign import capi "hs-libpq.h &PQclear" p_PQclear :: FunPtr (Ptr PGresult -> IO ()) -foreign import capi unsafe "hs-libpq.h PQresultStatus" +foreign import capi "hs-libpq.h PQresultStatus" c_PQresultStatus :: Ptr PGresult -> IO CInt -foreign import capi unsafe "hs-libpq.h PQresStatus" +foreign import capi "hs-libpq.h PQresStatus" c_PQresStatus :: CInt -> IO CString -foreign import capi unsafe "hs-libpq.h PQresultErrorMessage" +foreign import capi "hs-libpq.h PQresultErrorMessage" c_PQresultErrorMessage :: Ptr PGresult -> IO CString foreign import capi "hs-libpq.h PQresultErrorField" c_PQresultErrorField :: Ptr PGresult -> CInt -> IO CString -foreign import capi unsafe "hs-libpq.h PQntuples" +foreign import capi "hs-libpq.h PQntuples" c_PQntuples :: Ptr PGresult -> CInt -foreign import capi unsafe "hs-libpq.h PQnfields" +foreign import capi "hs-libpq.h PQnfields" c_PQnfields :: Ptr PGresult -> CInt -foreign import capi unsafe "hs-libpq.h PQfname" +foreign import capi "hs-libpq.h PQfname" c_PQfname :: Ptr PGresult -> CInt -> IO CString -foreign import capi unsafe "hs-libpq.h PQfnumber" +foreign import capi "hs-libpq.h PQfnumber" c_PQfnumber :: Ptr PGresult -> CString -> IO CInt -foreign import capi unsafe "hs-libpq.h PQftable" +foreign import capi "hs-libpq.h PQftable" c_PQftable :: Ptr PGresult -> CInt -> IO Oid -foreign import capi unsafe "hs-libpq.h PQftablecol" +foreign import capi "hs-libpq.h PQftablecol" c_PQftablecol :: Ptr PGresult -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQfformat" +foreign import capi "hs-libpq.h PQfformat" c_PQfformat :: Ptr PGresult -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQftype" +foreign import capi "hs-libpq.h PQftype" c_PQftype :: Ptr PGresult -> CInt -> IO Oid -foreign import capi unsafe "hs-libpq.h PQfmod" +foreign import capi "hs-libpq.h PQfmod" c_PQfmod :: Ptr PGresult -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQfsize" +foreign import capi "hs-libpq.h PQfsize" c_PQfsize :: Ptr PGresult -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQgetvalue" +foreign import capi "hs-libpq.h PQgetvalue" c_PQgetvalue :: Ptr PGresult -> CInt -> CInt -> IO CString -foreign import capi unsafe "hs-libpq.h PQgetisnull" +foreign import capi "hs-libpq.h PQgetisnull" c_PQgetisnull :: Ptr PGresult -> CInt -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQgetlength" +foreign import capi "hs-libpq.h PQgetlength" c_PQgetlength :: Ptr PGresult -> CInt -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQnparams" +foreign import capi "hs-libpq.h PQnparams" c_PQnparams :: Ptr PGresult -> IO CInt -foreign import capi unsafe "hs-libpq.h PQparamtype" +foreign import capi "hs-libpq.h PQparamtype" c_PQparamtype :: Ptr PGresult -> CInt -> IO Oid -foreign import capi unsafe "hs-libpq.h PQcmdStatus" +foreign import capi "hs-libpq.h PQcmdStatus" c_PQcmdStatus :: Ptr PGresult -> IO CString -foreign import capi unsafe "hs-libpq.h PQcmdTuples" +foreign import capi "hs-libpq.h PQcmdTuples" c_PQcmdTuples :: Ptr PGresult -> IO CString foreign import capi "hs-libpq.h PQescapeStringConn" @@ -290,38 +290,38 @@ foreign import capi "hs-libpq.h PQunescapeBytea" -> Ptr CSize -> IO (Ptr Word8) -- Actually (IO (Ptr CUChar)) -foreign import capi unsafe "hs-libpq.h PQescapeIdentifier" +foreign import capi "hs-libpq.h PQescapeIdentifier" c_PQescapeIdentifier :: Ptr PGconn -> CString -> CSize -> IO CString -foreign import capi unsafe "hs-libpq.h &PQfreemem" +foreign import capi "hs-libpq.h &PQfreemem" p_PQfreemem :: FunPtr (Ptr a -> IO ()) -foreign import capi unsafe "hs-libpq.h PQfreemem" +foreign import capi "hs-libpq.h PQfreemem" c_PQfreemem :: Ptr a -> IO () ------------------------------------------------------------------------------- -- FFI imports: noticebuffers ------------------------------------------------------------------------------- -foreign import capi unsafe "hs-libpq.h hs_postgresql_libpq_malloc_noticebuffer" +foreign import capi "hs-libpq.h hs_postgresql_libpq_malloc_noticebuffer" c_malloc_noticebuffer :: IO (Ptr CNoticeBuffer) -foreign import capi unsafe "hs-libpq.h hs_postgresql_libpq_free_noticebuffer" +foreign import capi "hs-libpq.h hs_postgresql_libpq_free_noticebuffer" c_free_noticebuffer :: Ptr CNoticeBuffer -> IO () -foreign import capi unsafe "hs-libpq.h hs_postgresql_libpq_get_notice" +foreign import capi "hs-libpq.h hs_postgresql_libpq_get_notice" c_get_notice :: Ptr CNoticeBuffer -> IO (Ptr PGnotice) -foreign import capi unsafe "hs-libpq.h &hs_postgresql_libpq_discard_notices" +foreign import capi "hs-libpq.h &hs_postgresql_libpq_discard_notices" p_discard_notices :: FunPtr NoticeReceiver -foreign import capi unsafe "hs-libpq.h &hs_postgresql_libpq_store_notices" +foreign import capi "hs-libpq.h &hs_postgresql_libpq_store_notices" p_store_notices :: FunPtr NoticeReceiver -foreign import capi unsafe "hs-libpq.h PQsetNoticeReceiver" +foreign import capi "hs-libpq.h PQsetNoticeReceiver" c_PQsetNoticeReceiver :: Ptr PGconn -> FunPtr NoticeReceiver -> Ptr CNoticeBuffer -> IO (FunPtr NoticeReceiver) ------------------------------------------------------------------------------- From d7a3a7d29057d955ef3584ace1b2e1370f88e88d Mon Sep 17 00:00:00 2001 From: Oleg Grenrus Date: Sat, 29 Jul 2023 21:24:38 +0300 Subject: [PATCH 2/2] Bump version to 0.10.0.0 --- CHANGELOG.md | 13 +++++++++++++ postgresql-libpq.cabal | 3 +-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5375c1c..baedb68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +0.10.0.0 +-------- + +There are technicallly two breaking changes in this release, +but they shouldn't affect anyone not doing anything weird. + +- Binary parameters are passed without copying. +- FFI functions are imported without `unsafe`. Most uses were incorrect. + We make all calls "safe", as checking whether libpq functions do IO + or may call a notifier (potentially calling back into Haskell), + is virtually impossible for all versions of libpq. + (The above properties are not specified in the documentation). + 0.9.5.0 ------- diff --git a/postgresql-libpq.cabal b/postgresql-libpq.cabal index dd75544..29544dd 100644 --- a/postgresql-libpq.cabal +++ b/postgresql-libpq.cabal @@ -1,7 +1,6 @@ cabal-version: 2.4 name: postgresql-libpq -version: 0.9.5.0 -x-revision: 1 +version: 0.10.0.0 synopsis: low-level binding to libpq description: This is a binding to libpq: the C application