Skip to content
Open
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
12 changes: 10 additions & 2 deletions mempack-scls/mempack-1.0/Data/MemPack/Extra.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import Data.ByteString.Lazy qualified as BSL
import Data.MemPack
import Data.MemPack.Buffer
import Data.MemPack.Error
import Data.Primitive.ByteArray
import Data.Primitive.Ptr
import Data.String (IsString)
import Data.Text qualified as T
Expand Down Expand Up @@ -240,12 +241,19 @@ hPutBuffer handle u =
buffer
u
( \bytes -> do
withForeignPtr (pinnedByteArrayToForeignPtr bytes) $ \ptr -> do
pinnedBytes <- pinIfNeeded (ByteArray bytes)
withForeignPtr (byteArrayAsForeignPtr pinnedBytes) $ \ptr -> do
hPutBuf handle ptr len
)
(\addr -> hPutBuf handle (Ptr addr) len) -- Write Ptr#
(\addr -> hPutBuf handle (Ptr addr) len)
where
len = bufferByteCount u
pinIfNeeded bytes
| isByteArrayPinned bytes = return bytes
| otherwise = do
dest <- newPinnedByteArray len
copyByteArray dest 0 bytes 0 len
unsafeFreezeByteArray dest

runDecode :: (IsString e) => Fail e a -> Either e a
runDecode f = runFailLast f
15 changes: 12 additions & 3 deletions mempack-scls/mempack-2.0/Data/MemPack/Extra.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import Data.ByteString.Lazy qualified as BSL
import Data.MemPack
import Data.MemPack.Buffer
import Data.MemPack.Error
import Data.Primitive.ByteArray
import Data.Primitive.Ptr
import Data.Text qualified as T
import Data.Typeable
Expand Down Expand Up @@ -245,12 +246,20 @@ hPutBuffer handle u =
buffer
u
( \bytes off -> do
withForeignPtr (pinnedByteArrayToForeignPtr bytes) $ \ptr -> do
hPutBuf handle (ptr `plusPtr` (I# off)) (len - (I# off))
(pinnedBytes, offset) <- pinIfNeeded (ByteArray bytes) (I# off)
withForeignPtr (byteArrayAsForeignPtr pinnedBytes) $ \ptr -> do
hPutBuf handle (ptr `plusPtr` offset) (len - offset)
)
(\addr -> hPutBuf handle (Ptr addr) len) -- Write Ptr#
(\addr -> hPutBuf handle (Ptr addr) len)
where
len = bufferByteCount u
pinIfNeeded bytes off
| isByteArrayPinned bytes = return (bytes, off)
| otherwise = do
let l = len - off
dest <- newPinnedByteArray l
copyByteArray dest 0 bytes off l
(,0) <$> unsafeFreezeByteArray dest
Comment on lines +249 to +262
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In hPutBuffer, the unpinned path in pinIfNeeded allocates a pinned buffer of length len - off but hPutBuf is still called with len - offset, which equals the original len when offset is 0. For unpinned ByteArrays where off > 0, this causes hPutBuf to read past the end of the newly allocated buffer and send extra bytes from adjacent memory to the Handle, potentially leaking sensitive process data or causing memory corruption. Adjust the logic so that the length passed to hPutBuf always matches the actual size of pinnedBytes (i.e., the copied slice), rather than the original buffer length.

Copilot uses AI. Check for mistakes.

runDecode :: (IsString e) => (forall s. FailT e (ST s) a) -> Either e a
runDecode f = runST (runFailLastT f)
Loading