xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_required_insert_count.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/qpack/qpack_required_insert_count.h"
6 
7 #include <limits>
8 
9 #include "quiche/quic/platform/api/quic_logging.h"
10 
11 namespace quic {
12 
QpackEncodeRequiredInsertCount(uint64_t required_insert_count,uint64_t max_entries)13 uint64_t QpackEncodeRequiredInsertCount(uint64_t required_insert_count,
14                                         uint64_t max_entries) {
15   if (required_insert_count == 0) {
16     return 0;
17   }
18 
19   return required_insert_count % (2 * max_entries) + 1;
20 }
21 
QpackDecodeRequiredInsertCount(uint64_t encoded_required_insert_count,uint64_t max_entries,uint64_t total_number_of_inserts,uint64_t * required_insert_count)22 bool QpackDecodeRequiredInsertCount(uint64_t encoded_required_insert_count,
23                                     uint64_t max_entries,
24                                     uint64_t total_number_of_inserts,
25                                     uint64_t* required_insert_count) {
26   if (encoded_required_insert_count == 0) {
27     *required_insert_count = 0;
28     return true;
29   }
30 
31   // |max_entries| is calculated by dividing an unsigned 64-bit integer by 32,
32   // precluding all calculations in this method from overflowing.
33   QUICHE_DCHECK_LE(max_entries, std::numeric_limits<uint64_t>::max() / 32);
34 
35   if (encoded_required_insert_count > 2 * max_entries) {
36     return false;
37   }
38 
39   *required_insert_count = encoded_required_insert_count - 1;
40   QUICHE_DCHECK_LT(*required_insert_count,
41                    std::numeric_limits<uint64_t>::max() / 16);
42 
43   uint64_t current_wrapped = total_number_of_inserts % (2 * max_entries);
44   QUICHE_DCHECK_LT(current_wrapped, std::numeric_limits<uint64_t>::max() / 16);
45 
46   if (current_wrapped >= *required_insert_count + max_entries) {
47     // Required Insert Count wrapped around 1 extra time.
48     *required_insert_count += 2 * max_entries;
49   } else if (current_wrapped + max_entries < *required_insert_count) {
50     // Decoder wrapped around 1 extra time.
51     current_wrapped += 2 * max_entries;
52   }
53 
54   if (*required_insert_count >
55       std::numeric_limits<uint64_t>::max() - total_number_of_inserts) {
56     return false;
57   }
58 
59   *required_insert_count += total_number_of_inserts;
60 
61   // Prevent underflow, also disallow invalid value 0 for Required Insert Count.
62   if (current_wrapped >= *required_insert_count) {
63     return false;
64   }
65 
66   *required_insert_count -= current_wrapped;
67 
68   return true;
69 }
70 
71 }  // namespace quic
72