new file mode 100644
@@ -0,0 +1,45 @@
+From dddd93ac995ac382e4ec9496509f24003bd72c30 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= <pzacik@redhat.com>
+Date: Wed, 3 Jun 2026 12:56:09 +0200
+Subject: [PATCH] CVE-2026-59848 sftp: Initialize sftp_request_queue ptr in
+ sftp_free
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavol Žáčik <pzacik@redhat.com>
+Reviewed-by: Jakub Jelen <jjelen@redhat.com>
+
+CVE: CVE-2026-59848
+Upstream-Status: Backport [https://git.libssh.org/projects/libssh.git/commit/?id=5309aefd99e1775db40bf20869f1fb1cc6c787be]
+
+Backport Changes:
+- Adjusted hunk context for the consolidated libssh 0.10.6 SFTP
+ implementation; the pointer initialization is unchanged from upstream.
+- Omitted the upstream tests/client/torture_sftp_request_id.c follow-up hunk
+ because CVE-2026-59848.patch introduces the backported regression test
+ directly with sftp_read_and_dispatch(); there is no intermediate
+ sftp_recv_response_msg() version to update.
+
+(cherry picked from commit 00876f7658fd265682708572122502188fa22076)
+(cherry picked from commit 5309aefd99e1775db40bf20869f1fb1cc6c787be)
+Signed-off-by: Hetvi Thakar <hthakar@cisco.com>
+---
+ src/sftp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/sftp.c b/src/sftp.c
+index e6755e2b..ff6e5200 100644
+--- a/src/sftp.c
++++ b/src/sftp.c
+@@ -371,7 +371,7 @@ void sftp_server_free(sftp_session sftp)
+
+ void sftp_free(sftp_session sftp)
+ {
+- sftp_request_queue ptr;
++ sftp_request_queue ptr = NULL;
+ struct ssh_iterator *id_it = NULL;
+
+ if (sftp == NULL) {
+--
+2.35.6
new file mode 100644
@@ -0,0 +1,684 @@
+From ef75e652dd2808c27251da4d03feef84d158c1de Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= <pzacik@redhat.com>
+Date: Mon, 1 Jun 2026 16:33:03 +0200
+Subject: [PATCH] CVE-2026-59848 sftp: handle responses with unknown request
+ IDs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This adds a new field to sftp_session_struct,
+containing a list of outstanding request IDs.
+An ID is added to the list when a request
+is constructed and removed when the corresponding
+request is received. If a client receives a response
+with an unknown request ID, it reports an error.
+
+Storing responses with unknown request IDs in
+the response queue could be abused by a malicious
+SFTP server which could deplete client memory
+this way.
+
+Signed-off-by: Pavol Žáčik <pzacik@redhat.com>
+Reviewed-by: Jakub Jelen <jjelen@redhat.com>
+
+CVE: CVE-2026-59848
+Upstream-Status: Backport [https://git.libssh.org/projects/libssh.git/commit/?id=a30a51003205744c10ba4439306f555206ae8497]
+
+Backport Changes:
+- Consolidated the upstream src/sftp_common.c and src/sftp_aio.c changes
+ into src/sftp.c, where libssh 0.10.6 implements response dispatch,
+ request-ID allocation, and asynchronous SFTP reads.
+- Kept sftp_get_new_id() static instead of exporting it through
+ sftp_priv.h because all 20 request-producing call sites in 0.10.6 are
+ in src/sftp.c; newer-only SFTP API call sites are absent.
+- Retained the 0.10.6 request construction order and free the existing
+ request buffer when request-ID tracking fails.
+- Adapted the unknown-ID regression test to call
+ sftp_read_and_dispatch() and verify the response queue remains empty;
+ 0.10.6 does not provide sftp_recv_response_msg().
+
+(cherry picked from commit 26147eb4767937c797f97ff3b1b1663384232417)
+(cherry picked from commit a30a51003205744c10ba4439306f555206ae8497)
+Signed-off-by: Hetvi Thakar <hthakar@cisco.com>
+---
+ include/libssh/sftp.h | 1 +
+ src/sftp.c | 210 ++++++++++++++++++++++---
+ tests/client/CMakeLists.txt | 1 +
+ tests/client/torture_sftp_request_id.c | 183 +++++++++++++++++++++
+ 4 files changed, 369 insertions(+), 26 deletions(-)
+ create mode 100644 tests/client/torture_sftp_request_id.c
+
+diff --git a/include/libssh/sftp.h b/include/libssh/sftp.h
+index c713466e..984c4eb7 100644
+--- a/include/libssh/sftp.h
++++ b/include/libssh/sftp.h
+@@ -90,6 +90,7 @@ struct sftp_session_struct {
+ void **handles;
+ sftp_ext ext;
+ sftp_packet read_packet;
++ struct ssh_list *outstanding_ids;
+ };
+
+ struct sftp_packet_struct {
+diff --git a/src/sftp.c b/src/sftp.c
+index 2194a9ef..e6755e2b 100644
+--- a/src/sftp.c
++++ b/src/sftp.c
+@@ -149,6 +149,12 @@ sftp_session sftp_new(ssh_session session)
+ goto error;
+ }
+
++ sftp->outstanding_ids = ssh_list_new();
++ if (sftp->outstanding_ids == NULL) {
++ ssh_set_error_oom(session);
++ goto error;
++ }
++
+ if (ssh_channel_open_session(sftp->channel)) {
+ goto error;
+ }
+@@ -165,6 +171,7 @@ error:
+ if (sftp->channel != NULL) {
+ ssh_channel_free(sftp->channel);
+ }
++ ssh_list_free(sftp->outstanding_ids);
+ if (sftp->read_packet != NULL) {
+ if (sftp->read_packet->payload != NULL) {
+ SSH_BUFFER_FREE(sftp->read_packet->payload);
+@@ -196,6 +203,12 @@ sftp_new_channel(ssh_session session, ssh_channel channel)
+ goto error;
+ }
+
++ sftp->outstanding_ids = ssh_list_new();
++ if (sftp->outstanding_ids == NULL) {
++ ssh_set_error_oom(session);
++ goto error;
++ }
++
+ sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct));
+ if (sftp->read_packet == NULL) {
+ ssh_set_error_oom(session);
+@@ -217,6 +230,7 @@ error:
+ if (sftp->ext != NULL) {
+ sftp_ext_free(sftp->ext);
+ }
++ ssh_list_free(sftp->outstanding_ids);
+ if (sftp->read_packet != NULL) {
+ if (sftp->read_packet->payload != NULL) {
+ SSH_BUFFER_FREE(sftp->read_packet->payload);
+@@ -358,6 +372,7 @@ void sftp_server_free(sftp_session sftp)
+ void sftp_free(sftp_session sftp)
+ {
+ sftp_request_queue ptr;
++ struct ssh_iterator *id_it = NULL;
+
+ if (sftp == NULL) {
+ return;
+@@ -384,6 +399,12 @@ void sftp_free(sftp_session sftp)
+
+ sftp_ext_free(sftp->ext);
+
++ id_it = ssh_list_get_iterator(sftp->outstanding_ids);
++ for (; id_it != NULL; id_it = id_it->next) {
++ free((uint32_t *)id_it->data);
++ }
++ ssh_list_free(sftp->outstanding_ids);
++
+ SAFE_FREE(sftp);
+ }
+
+@@ -571,6 +592,8 @@ static sftp_message sftp_get_message(sftp_packet packet)
+ {
+ sftp_session sftp = packet->sftp;
+ sftp_message msg = NULL;
++ struct ssh_iterator *id_it = NULL;
++ bool id_found = false;
+ int rc;
+
+ switch(packet->type) {
+@@ -618,6 +641,28 @@ static sftp_message sftp_get_message(sftp_packet packet)
+ msg->id,
+ msg->packet_type);
+
++ /* Validate that this ID is in our outstanding requests list */
++ id_it = ssh_list_get_iterator(sftp->outstanding_ids);
++ for (; id_it != NULL; id_it = id_it->next) {
++ uint32_t *stored_id = (uint32_t *)id_it->data;
++ if (*stored_id == msg->id) {
++ id_found = true;
++ ssh_list_remove(sftp->outstanding_ids, id_it);
++ free(stored_id);
++ break;
++ }
++ }
++
++ if (!id_found) {
++ ssh_set_error(packet->sftp->session,
++ SSH_FATAL,
++ "Unknown request ID %" PRIu32,
++ msg->id);
++ sftp_message_free(msg);
++ sftp_set_error(packet->sftp, SSH_FX_FAILURE);
++ return NULL;
++ }
++
+ return msg;
+ }
+
+@@ -902,13 +947,46 @@ static sftp_message sftp_dequeue(sftp_session sftp, uint32_t id){
+ return NULL;
+ }
+
+-/*
+- * Assigns a new SFTP ID for new requests and assures there is no collision
+- * between them.
+- * Returns a new ID ready to use in a request
++/**
++ * @brief Assigns a new SFTP ID for new requests and assures there is no
++ * collision between them.
++ *
++ * @param sftp The sftp session handle.
++ * @param id_out Pointer to store the new ID.
++ *
++ * @returns SSH_OK on success with the new ID stored in *id
++ * @returns SSH_ERROR on failure with the sftp and ssh errors set
+ */
+-static inline uint32_t sftp_get_new_id(sftp_session session) {
+- return ++session->id_counter;
++static int sftp_get_new_id(sftp_session sftp, uint32_t *id_out)
++{
++ uint32_t *id = NULL;
++ int rc;
++
++ if (id_out == NULL) {
++ ssh_set_error_invalid(sftp->session);
++ sftp_set_error(sftp, SSH_FX_FAILURE);
++ return SSH_ERROR;
++ }
++
++ id = malloc(sizeof(uint32_t));
++ if (id == NULL) {
++ ssh_set_error_oom(sftp->session);
++ sftp_set_error(sftp, SSH_FX_FAILURE);
++ return SSH_ERROR;
++ }
++
++ *id = ++sftp->id_counter;
++ rc = ssh_list_append(sftp->outstanding_ids, id);
++ if (rc != SSH_OK) {
++ free(id);
++ ssh_set_error_oom(sftp->session);
++ sftp_set_error(sftp, SSH_FX_FAILURE);
++ return SSH_ERROR;
++ }
++
++ *id_out = *id;
++
++ return SSH_OK;
+ }
+
+ static sftp_status_message parse_status_msg(sftp_message msg){
+@@ -1029,7 +1107,11 @@ sftp_dir sftp_opendir(sftp_session sftp, const char *path)
+ return NULL;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(payload);
++ return NULL;
++ }
+
+ rc = ssh_buffer_pack(payload,
+ "ds",
+@@ -1571,7 +1653,11 @@ sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir)
+ return NULL;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(payload);
++ return NULL;
++ }
+
+ rc = ssh_buffer_pack(payload,
+ "dS",
+@@ -1704,7 +1790,11 @@ static int sftp_handle_close(sftp_session sftp, ssh_string handle)
+ return -1;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dS",
+@@ -1835,7 +1925,11 @@ sftp_file sftp_open(sftp_session sftp,
+ sftp_flags |= SSH_FXF_APPEND;
+ }
+ SSH_LOG(SSH_LOG_PACKET,"Opening file %s with sftp flags %x",file,sftp_flags);
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return NULL;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dsd",
+@@ -1946,7 +2040,11 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
+ return -1;
+ }
+
+- id = sftp_get_new_id(handle->sftp);
++ rc = sftp_get_new_id(handle->sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dSqd",
+@@ -2047,7 +2145,11 @@ int sftp_async_read_begin(sftp_file file, uint32_t len){
+ return -1;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dSqd",
+@@ -2173,7 +2275,11 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
+ return -1;
+ }
+
+- id = sftp_get_new_id(file->sftp);
++ rc = sftp_get_new_id(file->sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dSqdP",
+@@ -2291,7 +2397,11 @@ int sftp_unlink(sftp_session sftp, const char *file) {
+ return -1;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "ds",
+@@ -2366,7 +2476,11 @@ int sftp_rmdir(sftp_session sftp, const char *directory) {
+ return -1;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "ds",
+@@ -2443,7 +2557,11 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode)
+ attr.permissions = mode;
+ attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS;
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "ds",
+@@ -2538,7 +2656,11 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
+ return -1;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dss",
+@@ -2622,7 +2744,11 @@ int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr)
+ return -1;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "ds",
+@@ -2752,7 +2878,11 @@ int sftp_symlink(sftp_session sftp, const char *target, const char *dest) {
+ return -1;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ /* TODO check for version number if they ever fix it. */
+ if (ssh_get_openssh_version(sftp->session)) {
+@@ -2850,7 +2980,11 @@ char *sftp_readlink(sftp_session sftp, const char *path)
+ return NULL;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return NULL;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "ds",
+@@ -2976,7 +3110,11 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path)
+ return NULL;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return NULL;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dss",
+@@ -3051,7 +3189,11 @@ int sftp_fsync(sftp_file file)
+ return -1;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return -1;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dsS",
+@@ -3151,7 +3293,11 @@ sftp_statvfs_t sftp_fstatvfs(sftp_file file)
+ return NULL;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return NULL;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dsS",
+@@ -3238,7 +3384,11 @@ char *sftp_canonicalize_path(sftp_session sftp, const char *path)
+ return NULL;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return NULL;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "ds",
+@@ -3329,7 +3479,11 @@ static sftp_attributes sftp_xstat(sftp_session sftp,
+ return NULL;
+ }
+
+- id = sftp_get_new_id(sftp);
++ rc = sftp_get_new_id(sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return NULL;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "ds",
+@@ -3407,7 +3561,11 @@ sftp_attributes sftp_fstat(sftp_file file)
+ return NULL;
+ }
+
+- id = sftp_get_new_id(file->sftp);
++ rc = sftp_get_new_id(file->sftp, &id);
++ if (rc != SSH_OK) {
++ SSH_BUFFER_FREE(buffer);
++ return NULL;
++ }
+
+ rc = ssh_buffer_pack(buffer,
+ "dS",
+diff --git a/tests/client/CMakeLists.txt b/tests/client/CMakeLists.txt
+index 71e5182e..864478a7 100644
+--- a/tests/client/CMakeLists.txt
++++ b/tests/client/CMakeLists.txt
+@@ -49,6 +49,7 @@ if (WITH_SFTP)
+ torture_sftp_dir
+ torture_sftp_read
+ torture_sftp_fsync
++ torture_sftp_request_id
+ ${SFTP_BENCHMARK_TESTS})
+ endif (WITH_SFTP)
+
+diff --git a/tests/client/torture_sftp_request_id.c b/tests/client/torture_sftp_request_id.c
+new file mode 100644
+index 00000000..fe6d3f91
+--- /dev/null
++++ b/tests/client/torture_sftp_request_id.c
+@@ -0,0 +1,183 @@
++#include "config.h"
++
++#define LIBSSH_STATIC
++
++#include "sftp.c"
++#include "torture.h"
++
++#include <pwd.h>
++#include <sys/types.h>
++
++static int sshd_setup(void **state)
++{
++ torture_setup_sshd_server(state, false);
++
++ return 0;
++}
++
++static int sshd_teardown(void **state)
++{
++ torture_teardown_sshd_server(state);
++
++ return 0;
++}
++
++static int session_setup(void **state)
++{
++ struct torture_state *s = *state;
++ struct passwd *pwd = NULL;
++ int rc;
++
++ pwd = getpwnam("bob");
++ assert_non_null(pwd);
++
++ rc = setuid(pwd->pw_uid);
++ assert_return_code(rc, errno);
++
++ s->ssh.session = torture_ssh_session(s,
++ TORTURE_SSH_SERVER,
++ NULL,
++ TORTURE_SSH_USER_ALICE,
++ NULL);
++ assert_non_null(s->ssh.session);
++
++ s->ssh.tsftp = torture_sftp_session(s->ssh.session);
++ assert_non_null(s->ssh.tsftp);
++
++ return 0;
++}
++
++static int session_teardown(void **state)
++{
++ struct torture_state *s = *state;
++
++ torture_rmdirs(s->ssh.tsftp->testdir);
++ torture_sftp_close(s->ssh.tsftp);
++ ssh_disconnect(s->ssh.session);
++ ssh_free(s->ssh.session);
++
++ return 0;
++}
++
++static void torture_sftp_request_id_null(void **state)
++{
++ struct torture_state *s = *state;
++ struct torture_sftp *t = s->ssh.tsftp;
++ sftp_session sftp = t->sftp;
++ int rc;
++
++ rc = sftp_get_new_id(sftp, NULL);
++ assert_int_equal(rc, SSH_ERROR);
++}
++
++static void torture_sftp_request_id_add(void **state)
++{
++ struct torture_state *s = *state;
++ struct torture_sftp *t = s->ssh.tsftp;
++ sftp_session sftp = t->sftp;
++ uint32_t id1, id2;
++ int rc;
++ size_t count;
++
++ /* The list of IDs should be empty at first */
++ count = ssh_list_count(sftp->outstanding_ids);
++ assert_int_equal(count, 0);
++
++ /* Request a new ID */
++ rc = sftp_get_new_id(sftp, &id1);
++ assert_int_equal(rc, SSH_OK);
++
++ /* Check that the list has one ID now */
++ count = ssh_list_count(sftp->outstanding_ids);
++ assert_int_equal(count, 1);
++
++ /* Request another ID */
++ rc = sftp_get_new_id(sftp, &id2);
++ assert_int_equal(rc, SSH_OK);
++
++ /* Check that the IDs differ */
++ assert_int_not_equal(id1, id2);
++
++ /* Check that the list has two IDs now */
++ count = ssh_list_count(sftp->outstanding_ids);
++ assert_int_equal(count, 2);
++}
++
++static void torture_sftp_request_id_remove(void **state)
++{
++ struct torture_state *s = *state;
++ struct torture_sftp *t = s->ssh.tsftp;
++ sftp_session sftp = t->sftp;
++ sftp_attributes attr = NULL;
++ size_t count;
++
++ count = ssh_list_count(sftp->outstanding_ids);
++ assert_int_equal(count, 0);
++
++ /* We send a request and receive a response */
++ attr = sftp_stat(sftp, SSH_EXECUTABLE);
++ assert_non_null(attr);
++
++ /* The number of outstanding requests should be back to 0 */
++ count = ssh_list_count(sftp->outstanding_ids);
++ assert_int_equal(count, 0);
++
++ sftp_attributes_free(attr);
++}
++
++static void torture_sftp_request_id_unknown(void **state)
++{
++ struct torture_state *s = *state;
++ struct torture_sftp *t = s->ssh.tsftp;
++ sftp_session sftp = t->sftp;
++ ssh_buffer buffer = NULL;
++ uint32_t id = 0;
++ int rc;
++ size_t count;
++
++ count = ssh_list_count(sftp->outstanding_ids);
++ assert_int_equal(count, 0);
++
++ buffer = ssh_buffer_new();
++ assert_non_null(buffer);
++
++ rc = ssh_buffer_pack(buffer, "ds", id, "/tmp");
++ assert_int_equal(rc, SSH_OK);
++
++ /* Send a request without saving the request ID */
++ rc = sftp_packet_write(sftp, SSH_FXP_OPENDIR, buffer);
++ assert_int_not_equal(rc, -1);
++ SSH_BUFFER_FREE(buffer);
++
++ /* An attempt to receive the response should fail without queuing it */
++ rc = sftp_read_and_dispatch(sftp);
++ assert_int_equal(rc, -1);
++ assert_null(sftp->queue);
++}
++
++int torture_run_tests(void)
++{
++ int rc;
++ struct CMUnitTest tests[] = {
++ cmocka_unit_test_setup_teardown(torture_sftp_request_id_null,
++ session_setup,
++ session_teardown),
++ cmocka_unit_test_setup_teardown(torture_sftp_request_id_add,
++ session_setup,
++ session_teardown),
++ cmocka_unit_test_setup_teardown(torture_sftp_request_id_remove,
++ session_setup,
++ session_teardown),
++ cmocka_unit_test_setup_teardown(torture_sftp_request_id_unknown,
++ session_setup,
++ session_teardown),
++ };
++
++ ssh_init();
++
++ torture_filter_tests(tests);
++ rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
++ ssh_finalize();
++
++ return rc;
++}
+--
+2.35.6
@@ -34,11 +34,9 @@ SRC_URI = "git://git.libssh.org/projects/libssh.git;protocol=https;branch=stable
file://CVE-2026-0965.patch \
file://CVE-2026-59843.patch \
file://CVE-2026-59844.patch \
-<<<<<<< HEAD
-=======
- file://CVE-2026-59845.patch \
file://CVE-2026-59846.patch \
->>>>>>> b782f294a0 (libssh: Fix CVE-2026-59846)
+ file://CVE-2026-59848.patch \
+ file://CVE-2026-59848-regression.patch \
"
SRCREV = "10e09e273f69e149389b3e0e5d44b8c221c2e7f6"