From: djm@openbsd.org Date: Mon, 29 Jun 2026 01:53:21 +0000 (+0000) Subject: upstream: avoid situation where sftp_download() could get stuck in X-Git-Tag: V_10_4_P1~49 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c1cebbc7c69acfe5df07b4a95e4c32cebc3e105a;p=thirdparty%2Fopenssh-portable.git upstream: avoid situation where sftp_download() could get stuck in a loop if a broken server repeatedly returned zero length while reading a file. Identified by Swival scanner OpenBSD-Commit-ID: 53f1de5065ff01952d2abb51747c2418ce21cd96 --- diff --git a/sftp-client.c b/sftp-client.c index 69ef28cdc..1f031128e 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.c,v 1.185 2026/03/03 09:57:25 dtucker Exp $ */ +/* $OpenBSD: sftp-client.c,v 1.186 2026/06/29 01:53:21 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -1585,7 +1585,7 @@ sftp_download(struct sftp_conn *conn, const char *remote_path, { struct sshbuf *msg; u_char *handle; - int local_fd = -1, write_error; + int local_fd = -1, write_error, seen_zerolen = 0; int read_error, write_errno, lmodified = 0, reordered = 0, r; uint64_t offset = 0, size, highwater = 0, maxack = 0; u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; @@ -1733,6 +1733,11 @@ sftp_download(struct sftp_conn *conn, const char *remote_path, if (len > req->len) fatal("Received more data than asked for " "%zu > %zu", len, req->len); + if (len == 0) { + if (seen_zerolen) + fatal_f("server sent zero data length"); + seen_zerolen = 1; + } lmodified = 1; if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || atomicio(vwrite, local_fd, data, len) != len) && @@ -2446,7 +2451,7 @@ sftp_crossload(struct sftp_conn *from, struct sftp_conn *to, Attrib *a, int preserve_flag) { struct sshbuf *msg; - int write_error, read_error, r; + int write_error, read_error, r, seen_zerolen = 0; uint64_t offset = 0, size; u_int id, buflen, num_req, max_req, status = SSH2_FX_OK; u_int num_upload_req; @@ -2576,6 +2581,11 @@ sftp_crossload(struct sftp_conn *from, struct sftp_conn *to, if (len > req->len) fatal("Received more data than asked for " "%zu > %zu", len, req->len); + if (len == 0) { + if (seen_zerolen) + fatal_f("server sent zero data length"); + seen_zerolen = 1; + } /* Write this chunk out to the destination */ sshbuf_reset(msg);