Commit 63afe63914 for openssl.org

commit 63afe639141faf49a62611808651b2b80030c64b
Author: Nikola Pajkovsky <nikolap@openssl.org>
Date:   Thu Jul 16 14:15:56 2026 +0200

    quic: report SRTM entry match status via an output argument

    Coverity (CID 1696969, CHECKED_RETURN) flagged the ignored return value of
    ossl_quic_srtm_remove() in ch_enqueue_retire_conn_id(). The return value
    could not be usefully checked because 0 was overloaded to mean both "no
    matching entry" and a genuine internal failure (alloc_failed or an
    lhash consistency error).

    Give the return value a single meaning (1 on success, 0 on internal
    error) and report whether a matching entry was found through a new
    uint8_t *match output argument, which may be NULL if the caller does not
    need it.

    Resolved: https://scan5.scan.coverity.com/#/project-view/65138/10222?selectedIssue=1696969
    Signed-off-by: Nikola Pajkovsky <nikola@pajkovsky.cz>

    Reviewed-by: Bob Beck <beck@openssl.org>
    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Neil Horman <nhorman@openssl.org>
    MergeDate: Tue Jul 21 09:24:45 2026
    (Merged from https://github.com/openssl/openssl/pull/31974)

diff --git a/fuzz/quic-srtm.c b/fuzz/quic-srtm.c
index 6e152299e1..9eb4117adc 100644
--- a/fuzz/quic-srtm.c
+++ b/fuzz/quic-srtm.c
@@ -88,7 +88,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
                 continue; /* just stop */

             if (ossl_quic_srtm_remove(srtm, (void *)(uintptr_t)arg_opaque,
-                    arg_seq_num))
+                    arg_seq_num, NULL))
                 ossl_quic_srtm_check(srtm);
             break;

diff --git a/include/internal/quic_srtm.h b/include/internal/quic_srtm.h
index 1a8f55da5d..77c0af6ac4 100644
--- a/include/internal/quic_srtm.h
+++ b/include/internal/quic_srtm.h
@@ -11,6 +11,7 @@
 #define OSSL_INTERNAL_QUIC_SRTM_H
 #pragma once

+#include <stdint.h>
 #include "internal/e_os.h"
 #include "internal/time.h"
 #include "internal/quic_types.h"
@@ -69,11 +70,22 @@ void ossl_quic_srtm_free(QUIC_SRTM *srtm);
 int ossl_quic_srtm_add(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num,
     const QUIC_STATELESS_RESET_TOKEN *token);

-/*
- * Removes an entry by identifying it via its (opaque, seq_num) tuple.
- * Returns 1 if the entry was found and removed, and 0 if it was not found.
+/**
+ * \brief Removes an entry identified by its (opaque, seq_num) tuple.
+ *
+ * The absence of a matching entry is not an error.
+ *
+ * \param srtm     SRTM instance to remove the entry from.
+ * \param opaque   Opaque pointer identifying the entry.
+ * \param seq_num  Sequence number identifying the entry.
+ * \param match    If non-NULL, \c *match is set to 1 if a matching entry was
+ *                 found or to 0 if not. May be NULL if this information is not
+ *                 required.
+ *
+ * \return 1 on success and 0 on internal error.
  */
-int ossl_quic_srtm_remove(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num);
+int ossl_quic_srtm_remove(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num,
+    uint8_t *match);

 /*
  * Removes all entries (opaque, *) with the given opaque pointer.
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index aaabf5a432..99f131cb78 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -3325,7 +3325,8 @@ static int ch_enqueue_retire_conn_id(QUIC_CHANNEL *ch, uint64_t seq_num)
     WPACKET wpkt;
     size_t l;

-    ossl_quic_srtm_remove(ch->srtm, ch, seq_num);
+    if (!ossl_quic_srtm_remove(ch->srtm, ch, seq_num, NULL))
+        goto err;

     if ((buf_mem = BUF_MEM_new()) == NULL)
         goto err;
diff --git a/ssl/quic/quic_srtm.c b/ssl/quic/quic_srtm.c
index 1cc2ae6962..4c8ea10734 100644
--- a/ssl/quic/quic_srtm.c
+++ b/ssl/quic/quic_srtm.c
@@ -382,16 +382,24 @@ static int srtm_remove_from_rev(QUIC_SRTM *srtm, SRTM_ITEM *item)
     return 1;
 }

-int ossl_quic_srtm_remove(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num)
+int ossl_quic_srtm_remove(QUIC_SRTM *srtm, void *opaque, uint64_t seq_num,
+    uint8_t *match)
 {
     SRTM_ITEM *item, *prev = NULL;
+    uint8_t match_sink;
+
+    if (match == NULL)
+        match = &match_sink;
+    *match = 0;

     if (srtm->alloc_failed)
         return 0;

     if ((item = srtm_find(srtm, opaque, seq_num, NULL, &prev)) == NULL)
         /* No match */
-        return 0;
+        return 1;
+
+    *match = 1;

     /* Remove from forward mapping. */
     if (prev == NULL) {
diff --git a/test/quic_srtm_test.c b/test/quic_srtm_test.c
index 6a1d6f3618..7838d46a77 100644
--- a/test/quic_srtm_test.c
+++ b/test/quic_srtm_test.c
@@ -22,14 +22,17 @@ static int test_srtm(void)
     QUIC_SRTM *srtm;
     void *opaque = NULL;
     uint64_t seq_num = 0;
+    uint8_t match;

     if (!TEST_ptr(srtm = ossl_quic_srtm_new(NULL, NULL)))
         goto err;

     if (!TEST_true(ossl_quic_srtm_add(srtm, ptrs + 0, 0, &token_1))
         || !TEST_false(ossl_quic_srtm_add(srtm, ptrs + 0, 0, &token_1))
-        || !TEST_false(ossl_quic_srtm_remove(srtm, ptrs + 0, 1))
-        || !TEST_false(ossl_quic_srtm_remove(srtm, ptrs + 3, 0))
+        || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 0, 1, &match))
+        || !TEST_uint_eq(match, 0)
+        || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 3, 0, &match))
+        || !TEST_uint_eq(match, 0)
         || !TEST_true(ossl_quic_srtm_cull(srtm, ptrs + 3))
         || !TEST_true(ossl_quic_srtm_cull(srtm, ptrs + 3))
         || !TEST_true(ossl_quic_srtm_add(srtm, ptrs + 0, 1, &token_1))
@@ -38,7 +41,8 @@ static int test_srtm(void)
         || !TEST_true(ossl_quic_srtm_add(srtm, ptrs + 1, 0, &token_1))
         || !TEST_true(ossl_quic_srtm_add(srtm, ptrs + 2, 0, &token_2))
         || !TEST_true(ossl_quic_srtm_add(srtm, ptrs + 3, 3, &token_2))
-        || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 3, 3))
+        || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 3, 3, &match))
+        || !TEST_uint_eq(match, 1)
         || !TEST_true(ossl_quic_srtm_lookup(srtm, &token_1, 0, &opaque, &seq_num))
         || !TEST_ptr_eq(opaque, ptrs + 1)
         || !TEST_uint64_t_eq(seq_num, 0)
@@ -62,7 +66,8 @@ static int test_srtm(void)
         || !TEST_true(ossl_quic_srtm_lookup(srtm, &token_2, 0, &opaque, &seq_num))
         || !TEST_ptr_eq(opaque, ptrs + 2)
         || !TEST_uint64_t_eq(seq_num, 0)
-        || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 2, 0))
+        || !TEST_true(ossl_quic_srtm_remove(srtm, ptrs + 2, 0, &match))
+        || !TEST_uint_eq(match, 1)
         || !TEST_false(ossl_quic_srtm_lookup(srtm, &token_2, 0, &opaque, &seq_num)))
         goto err;

@@ -102,11 +107,11 @@ static int test_srtm_ops_mfail(void)
         || !ossl_quic_srtm_add(srtm, ptrs + 1, 0, &token_1)
         || !ossl_quic_srtm_add(srtm, ptrs + 2, 0, &token_2)
         || !ossl_quic_srtm_add(srtm, ptrs + 3, 3, &token_2)
-        || !ossl_quic_srtm_remove(srtm, ptrs + 3, 3)
+        || !ossl_quic_srtm_remove(srtm, ptrs + 3, 3, NULL)
         || !ossl_quic_srtm_lookup(srtm, &token_1, 0, &opaque, &seq_num)
         || !ossl_quic_srtm_cull(srtm, ptrs + 0)
         || !ossl_quic_srtm_lookup(srtm, &token_2, 0, &opaque, &seq_num)
-        || !ossl_quic_srtm_remove(srtm, ptrs + 2, 0))
+        || !ossl_quic_srtm_remove(srtm, ptrs + 2, 0, NULL))
         goto err;

     testresult = 1;