@@ -147,9 +147,22 @@ func compress(cctx, cctxDict *cctxWrapper, dst, src []byte, cd *CDict, compressi
147147 return dst
148148}
149149
150+ // noescape hides a pointer from escape analysis. It is the identity function
151+ // but escape analysis doesn't think the output depends on the input.
152+ // noescape is inlined and currently compiles down to zero instructions.
153+ // This is copied from go's strings.Builder. Allows us to use stack-allocated
154+ // slices.
155+ //go:nosplit
156+ //go:nocheckptr
157+ func noescape (p unsafe.Pointer ) unsafe.Pointer {
158+ x := uintptr (p )
159+ return unsafe .Pointer (x ^ 0 )
160+ }
161+
150162func compressInternal (cctx , cctxDict * cctxWrapper , dst , src []byte , cd * CDict , compressionLevel int , mustSucceed bool ) C.size_t {
151- dstHdr := (* reflect .SliceHeader )(unsafe .Pointer (& dst ))
152- srcHdr := (* reflect .SliceHeader )(unsafe .Pointer (& src ))
163+ // using noescape will allow this to work with stack-allocated slices
164+ dstHdr := (* reflect .SliceHeader )(noescape (unsafe .Pointer (& dst )))
165+ srcHdr := (* reflect .SliceHeader )(noescape (unsafe .Pointer (& src )))
153166
154167 if cd != nil {
155168 result := C .ZSTD_compress_usingCDict_wrapper (
@@ -180,6 +193,7 @@ func compressInternal(cctx, cctxDict *cctxWrapper, dst, src []byte, cd *CDict, c
180193 if mustSucceed {
181194 ensureNoError ("ZSTD_compressCCtx" , result )
182195 }
196+
183197 return result
184198}
185199
@@ -258,7 +272,7 @@ func decompress(dctx, dctxDict *dctxWrapper, dst, src []byte, dd *DDict) ([]byte
258272 }
259273
260274 // Slow path - resize dst to fit decompressed data.
261- srcHdr := (* reflect .SliceHeader )(unsafe .Pointer (& src ))
275+ srcHdr := (* reflect .SliceHeader )(noescape ( unsafe .Pointer (& src ) ))
262276 contentSize := C .ZSTD_getFrameContentSize_wrapper (unsafe .Pointer (srcHdr .Data ), C .size_t (len (src )))
263277 switch {
264278 case contentSize == C .ZSTD_CONTENTSIZE_UNKNOWN || contentSize > maxFrameContentSize :
@@ -290,8 +304,8 @@ func decompress(dctx, dctxDict *dctxWrapper, dst, src []byte, dd *DDict) ([]byte
290304
291305func decompressInternal (dctx , dctxDict * dctxWrapper , dst , src []byte , dd * DDict ) C.size_t {
292306 var (
293- dstHdr = (* reflect .SliceHeader )(unsafe .Pointer (& dst ))
294- srcHdr = (* reflect .SliceHeader )(unsafe .Pointer (& src ))
307+ dstHdr = (* reflect .SliceHeader )(noescape ( unsafe .Pointer (& dst ) ))
308+ srcHdr = (* reflect .SliceHeader )(noescape ( unsafe .Pointer (& src ) ))
295309 n C.size_t
296310 )
297311 if dd != nil {
0 commit comments