pool.c
Go to the documentation of this file.
1 /* Copyright (c) 2016, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include <openssl/pool.h>
16 
17 #include <assert.h>
18 #include <string.h>
19 
20 #include <openssl/bytestring.h>
21 #include <openssl/mem.h>
22 #include <openssl/thread.h>
23 
24 #include "../internal.h"
25 #include "internal.h"
26 
27 
29  return OPENSSL_hash32(buf->data, buf->len);
30 }
31 
32 static int CRYPTO_BUFFER_cmp(const CRYPTO_BUFFER *a, const CRYPTO_BUFFER *b) {
33  if (a->len != b->len) {
34  return 1;
35  }
36  return OPENSSL_memcmp(a->data, b->data, a->len);
37 }
38 
41  if (pool == NULL) {
42  return NULL;
43  }
44 
46  pool->bufs = lh_CRYPTO_BUFFER_new(CRYPTO_BUFFER_hash, CRYPTO_BUFFER_cmp);
47  if (pool->bufs == NULL) {
49  return NULL;
50  }
51 
52  CRYPTO_MUTEX_init(&pool->lock);
53 
54  return pool;
55 }
56 
58  if (pool == NULL) {
59  return;
60  }
61 
62 #if !defined(NDEBUG)
64  assert(lh_CRYPTO_BUFFER_num_items(pool->bufs) == 0);
66 #endif
67 
68  lh_CRYPTO_BUFFER_free(pool->bufs);
69  CRYPTO_MUTEX_cleanup(&pool->lock);
71 }
72 
74  if (!buf->data_is_static) {
75  OPENSSL_free(buf->data);
76  }
78 }
79 
81  int data_is_static,
83  if (pool != NULL) {
85  tmp.data = (uint8_t *) data;
86  tmp.len = len;
87 
89  CRYPTO_BUFFER *duplicate = lh_CRYPTO_BUFFER_retrieve(pool->bufs, &tmp);
90  if (data_is_static && duplicate != NULL && !duplicate->data_is_static) {
91  // If the new |CRYPTO_BUFFER| would have static data, but the duplicate
92  // does not, we replace the old one with the new static version.
93  duplicate = NULL;
94  }
95  if (duplicate != NULL) {
96  CRYPTO_refcount_inc(&duplicate->references);
97  }
99 
100  if (duplicate != NULL) {
101  return duplicate;
102  }
103  }
104 
105  CRYPTO_BUFFER *const buf = OPENSSL_malloc(sizeof(CRYPTO_BUFFER));
106  if (buf == NULL) {
107  return NULL;
108  }
109  OPENSSL_memset(buf, 0, sizeof(CRYPTO_BUFFER));
110 
111  if (data_is_static) {
112  buf->data = (uint8_t *)data;
113  buf->data_is_static = 1;
114  } else {
115  buf->data = OPENSSL_memdup(data, len);
116  if (len != 0 && buf->data == NULL) {
117  OPENSSL_free(buf);
118  return NULL;
119  }
120  }
121 
122  buf->len = len;
123  buf->references = 1;
124 
125  if (pool == NULL) {
126  return buf;
127  }
128 
129  buf->pool = pool;
130 
132  CRYPTO_BUFFER *duplicate = lh_CRYPTO_BUFFER_retrieve(pool->bufs, buf);
133  if (data_is_static && duplicate != NULL && !duplicate->data_is_static) {
134  // If the new |CRYPTO_BUFFER| would have static data, but the duplicate does
135  // not, we replace the old one with the new static version.
136  duplicate = NULL;
137  }
138  int inserted = 0;
139  if (duplicate == NULL) {
140  CRYPTO_BUFFER *old = NULL;
141  inserted = lh_CRYPTO_BUFFER_insert(pool->bufs, &old, buf);
142  // |old| may be non-NULL if a match was found but ignored. |pool->bufs| does
143  // not increment refcounts, so there is no need to clean up after the
144  // replacement.
145  } else {
146  CRYPTO_refcount_inc(&duplicate->references);
147  }
149 
150  if (!inserted) {
151  // We raced to insert |buf| into the pool and lost, or else there was an
152  // error inserting.
154  return duplicate;
155  }
156 
157  return buf;
158 }
159 
162  return crypto_buffer_new(data, len, /*data_is_static=*/0, pool);
163 }
164 
166  CRYPTO_BUFFER *const buf = OPENSSL_malloc(sizeof(CRYPTO_BUFFER));
167  if (buf == NULL) {
168  return NULL;
169  }
170  OPENSSL_memset(buf, 0, sizeof(CRYPTO_BUFFER));
171 
172  buf->data = OPENSSL_malloc(len);
173  if (len != 0 && buf->data == NULL) {
174  OPENSSL_free(buf);
175  return NULL;
176  }
177  buf->len = len;
178  buf->references = 1;
179 
180  *out_data = buf->data;
181  return buf;
182 }
183 
187 }
188 
190  const uint8_t *data, size_t len, CRYPTO_BUFFER_POOL *pool) {
191  return crypto_buffer_new(data, len, /*data_is_static=*/1, pool);
192 }
193 
195  if (buf == NULL) {
196  return;
197  }
198 
199  CRYPTO_BUFFER_POOL *const pool = buf->pool;
200  if (pool == NULL) {
201  if (CRYPTO_refcount_dec_and_test_zero(&buf->references)) {
202  // If a reference count of zero is observed, there cannot be a reference
203  // from any pool to this buffer and thus we are able to free this
204  // buffer.
206  }
207 
208  return;
209  }
210 
212  if (!CRYPTO_refcount_dec_and_test_zero(&buf->references)) {
213  CRYPTO_MUTEX_unlock_write(&buf->pool->lock);
214  return;
215  }
216 
217  // We have an exclusive lock on the pool, therefore no concurrent lookups can
218  // find this buffer and increment the reference count. Thus, if the count is
219  // zero there are and can never be any more references and thus we can free
220  // this buffer.
221  //
222  // Note it is possible |buf| is no longer in the pool, if it was replaced by a
223  // static version. If that static version was since removed, it is even
224  // possible for |found| to be NULL.
225  CRYPTO_BUFFER *found = lh_CRYPTO_BUFFER_retrieve(pool->bufs, buf);
226  if (found == buf) {
227  found = lh_CRYPTO_BUFFER_delete(pool->bufs, buf);
228  assert(found == buf);
229  (void)found;
230  }
231 
232  CRYPTO_MUTEX_unlock_write(&buf->pool->lock);
234 }
235 
237  // This is safe in the case that |buf->pool| is NULL because it's just
238  // standard reference counting in that case.
239  //
240  // This is also safe if |buf->pool| is non-NULL because, if it were racing
241  // with |CRYPTO_BUFFER_free| then the two callers must have independent
242  // references already and so the reference count will never hit zero.
243  CRYPTO_refcount_inc(&buf->references);
244  return 1;
245 }
246 
248  return buf->data;
249 }
250 
252  return buf->len;
253 }
254 
256  CBS_init(out, buf->data, buf->len);
257 }
CRYPTO_BUFFER_alloc
CRYPTO_BUFFER * CRYPTO_BUFFER_alloc(uint8_t **out_data, size_t len)
Definition: pool.c:165
crypto_buffer_st::references
CRYPTO_refcount_t references
Definition: third_party/boringssl-with-bazel/src/crypto/pool/internal.h:35
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
cbs_st
Definition: bytestring.h:39
OPENSSL_memcmp
static int OPENSSL_memcmp(const void *s1, const void *s2, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:811
CBS_data
#define CBS_data
Definition: boringssl_prefix_symbols.h:1057
internal.h
string.h
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
CRYPTO_BUFFER_up_ref
int CRYPTO_BUFFER_up_ref(CRYPTO_BUFFER *buf)
Definition: pool.c:236
CRYPTO_MUTEX_unlock_read
#define CRYPTO_MUTEX_unlock_read
Definition: boringssl_prefix_symbols.h:1127
inserted
bool inserted
Definition: event_engine/iomgr_event_engine/timer_heap_test.cc:110
OPENSSL_hash32
#define OPENSSL_hash32
Definition: boringssl_prefix_symbols.h:1873
CBS_len
#define CBS_len
Definition: boringssl_prefix_symbols.h:1089
crypto_buffer_st
Definition: third_party/boringssl-with-bazel/src/crypto/pool/internal.h:31
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
cbs
const CBS * cbs
Definition: third_party/boringssl-with-bazel/src/crypto/trust_token/internal.h:107
CRYPTO_MUTEX_init
#define CRYPTO_MUTEX_init
Definition: boringssl_prefix_symbols.h:1124
CBS_init
#define CBS_init
Definition: boringssl_prefix_symbols.h:1085
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
OPENSSL_memset
static void * OPENSSL_memset(void *dst, int c, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:835
CRYPTO_BUFFER_new_from_CBS
CRYPTO_BUFFER * CRYPTO_BUFFER_new_from_CBS(const CBS *cbs, CRYPTO_BUFFER_POOL *pool)
Definition: pool.c:184
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
OPENSSL_malloc
#define OPENSSL_malloc
Definition: boringssl_prefix_symbols.h:1885
bytestring.h
CRYPTO_BUFFER_data
const uint8_t * CRYPTO_BUFFER_data(const CRYPTO_BUFFER *buf)
Definition: pool.c:247
gen_stats_data.found
bool found
Definition: gen_stats_data.py:61
CRYPTO_BUFFER_len
size_t CRYPTO_BUFFER_len(const CRYPTO_BUFFER *buf)
Definition: pool.c:251
crypto_buffer_new
static CRYPTO_BUFFER * crypto_buffer_new(const uint8_t *data, size_t len, int data_is_static, CRYPTO_BUFFER_POOL *pool)
Definition: pool.c:80
CRYPTO_BUFFER_new
CRYPTO_BUFFER * CRYPTO_BUFFER_new(const uint8_t *data, size_t len, CRYPTO_BUFFER_POOL *pool)
Definition: pool.c:160
pool.h
CRYPTO_BUFFER_init_CBS
void CRYPTO_BUFFER_init_CBS(const CRYPTO_BUFFER *buf, CBS *out)
Definition: pool.c:255
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
crypto_buffer_free_object
static void crypto_buffer_free_object(CRYPTO_BUFFER *buf)
Definition: pool.c:73
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
CRYPTO_MUTEX_lock_read
#define CRYPTO_MUTEX_lock_read
Definition: boringssl_prefix_symbols.h:1125
CRYPTO_MUTEX_cleanup
#define CRYPTO_MUTEX_cleanup
Definition: boringssl_prefix_symbols.h:1123
CRYPTO_BUFFER_POOL_new
CRYPTO_BUFFER_POOL * CRYPTO_BUFFER_POOL_new(void)
Definition: pool.c:39
OPENSSL_memdup
#define OPENSSL_memdup
Definition: boringssl_prefix_symbols.h:1887
CRYPTO_MUTEX_lock_write
#define CRYPTO_MUTEX_lock_write
Definition: boringssl_prefix_symbols.h:1126
CRYPTO_BUFFER_new_from_static_data_unsafe
CRYPTO_BUFFER * CRYPTO_BUFFER_new_from_static_data_unsafe(const uint8_t *data, size_t len, CRYPTO_BUFFER_POOL *pool)
Definition: pool.c:189
crypto_buffer_pool_st
Definition: third_party/boringssl-with-bazel/src/crypto/pool/internal.h:39
pool
InternalDescriptorPool * pool
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:807
CRYPTO_refcount_inc
#define CRYPTO_refcount_inc
Definition: boringssl_prefix_symbols.h:1191
CRYPTO_BUFFER_POOL_free
void CRYPTO_BUFFER_POOL_free(CRYPTO_BUFFER_POOL *pool)
Definition: pool.c:57
CRYPTO_BUFFER_cmp
static int CRYPTO_BUFFER_cmp(const CRYPTO_BUFFER *a, const CRYPTO_BUFFER *b)
Definition: pool.c:32
mem.h
crypto_buffer_st::data_is_static
int data_is_static
Definition: third_party/boringssl-with-bazel/src/crypto/pool/internal.h:36
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
autogen_x86imm.tmp
tmp
Definition: autogen_x86imm.py:12
CRYPTO_BUFFER_free
void CRYPTO_BUFFER_free(CRYPTO_BUFFER *buf)
Definition: pool.c:194
thread.h
CRYPTO_BUFFER_hash
static uint32_t CRYPTO_BUFFER_hash(const CRYPTO_BUFFER *buf)
Definition: pool.c:28
OPENSSL_free
#define OPENSSL_free
Definition: boringssl_prefix_symbols.h:1869
CRYPTO_MUTEX_unlock_write
#define CRYPTO_MUTEX_unlock_write
Definition: boringssl_prefix_symbols.h:1128
binary_size.old
string old
Definition: binary_size.py:128
CRYPTO_refcount_dec_and_test_zero
#define CRYPTO_refcount_dec_and_test_zero
Definition: boringssl_prefix_symbols.h:1190


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:44