@@ -344,7 +344,12 @@ func Hijack[REQ sshfx.Packet](srv *Server, fn func(context.Context, REQ) error)
344344// This is really only useful for supporting newer versions of the SFTP standard.
345345func HijackWithResponse [REQ , RESP sshfx.Packet ](srv * Server , fn func (context.Context , REQ ) (RESP , error )) error {
346346 wrap := wrapHandler (func (ctx context.Context , req sshfx.Packet ) (sshfx.Packet , error ) {
347- return fn (ctx , req .(REQ ))
347+ resp , err := fn (ctx , req .(REQ ))
348+ if err != nil {
349+ // We have to convert maybe typed-zero to untyped-nil.
350+ return nil , err
351+ }
352+ return resp , nil
348353 })
349354
350355 var pkt REQ
@@ -515,6 +520,7 @@ func (srv *Server) handle(req sshfx.Packet, hint []byte, maxDataLen uint32) (ssh
515520
516521 if len (srv .hijacks ) > 0 {
517522 if fn := srv .hijacks [req .Type ()]; fn != nil {
523+ // Hijack takes care of wrapping the getter into an untyped-nil on error.
518524 return get (srv , req , fn )
519525 }
520526 }
@@ -595,7 +601,13 @@ func (srv *Server) handle(req sshfx.Packet, hint []byte, maxDataLen uint32) (ssh
595601
596602 case * openssh.StatVFSExtendedPacket :
597603 if statvfser , ok := srv .Handler .(StatVFSServerHandler ); ok {
598- return get (srv , req , statvfser .StatVFS )
604+ resp , err := get (srv , req , statvfser .StatVFS )
605+ if err != nil {
606+ // We have to convert typed-nil to untyped-nil.
607+ return nil , err
608+ }
609+
610+ return resp , nil
599611 }
600612
601613 case interface { GetHandle () string }:
@@ -610,15 +622,27 @@ func (srv *Server) handle(req sshfx.Packet, hint []byte, maxDataLen uint32) (ssh
610622
611623 case * openssh.FStatVFSExtendedPacket :
612624 if statvfser , ok := file .(StatVFSFileHandler ); ok {
613- return statvfser .StatVFS ()
625+ resp , err := statvfser .StatVFS ()
626+ if err != nil {
627+ // We have to convert typed-nil to untyped-nil.
628+ return nil , err
629+ }
630+
631+ return resp , nil
614632 }
615633
616634 if statvfser , ok := srv .Handler .(StatVFSServerHandler ); ok {
617635 req := & openssh.StatVFSExtendedPacket {
618636 Path : file .Name (),
619637 }
620638
621- return get (srv , req , statvfser .StatVFS )
639+ resp , err := get (srv , req , statvfser .StatVFS )
640+ if err != nil {
641+ // We have to convert typed-nil to untyped-nil.
642+ return nil , err
643+ }
644+
645+ return resp , nil
622646 }
623647 }
624648 }
@@ -701,7 +725,7 @@ func (srv *Server) handle(req sshfx.Packet, hint []byte, maxDataLen uint32) (ssh
701725 }
702726
703727 hint = slices .Grow (hint [:0 ], int (req .Length ))[:req .Length ]
704-
728+
705729 n , err := file .ReadAt (hint , int64 (req .Offset ))
706730 if err != nil {
707731 // We cannot return results AND a status like SSH_FX_EOF,
@@ -729,7 +753,8 @@ func (srv *Server) handle(req sshfx.Packet, hint []byte, maxDataLen uint32) (ssh
729753 return nil , io .ErrShortWrite
730754 }
731755
732- return nil , nil
756+ // explicitly return statusOK here, rather than both nil.
757+ return statusOK , nil
733758
734759 case * sshfx.FStatPacket :
735760 attrs , err := file .Stat ()
0 commit comments