diff options
author | jsing <> | 2022-02-18 17:30:13 +0000 |
---|---|---|
committer | jsing <> | 2022-02-18 17:30:13 +0000 |
commit | 8a99d590553fa0c8387169b9ba29360c3a52dab8 (patch) | |
tree | b2a0af2ad0615017288f9b467da71f7c2e8ab3c9 /src/lib | |
parent | a72b3400b5022f9456bfb2f05ccf5d617c73fc62 (diff) | |
download | openbsd-8a99d590553fa0c8387169b9ba29360c3a52dab8.tar.gz openbsd-8a99d590553fa0c8387169b9ba29360c3a52dab8.tar.bz2 openbsd-8a99d590553fa0c8387169b9ba29360c3a52dab8.zip |
Clean up and simplify memory BIO code.
This is a first pass that uses sensible and consistent names for variables.
Call the BIO 'bio' (instead of 'a', 'b', 'bp', or 'h'), drop a bunch of
unnecessary casts, simplify some logic and add additional error checking.
With input from and ok tb@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/bio/bss_mem.c | 263 |
1 files changed, 139 insertions, 124 deletions
diff --git a/src/lib/libcrypto/bio/bss_mem.c b/src/lib/libcrypto/bio/bss_mem.c index 3632ffed0b..594351b92b 100644 --- a/src/lib/libcrypto/bio/bss_mem.c +++ b/src/lib/libcrypto/bio/bss_mem.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bss_mem.c,v 1.18 2022/01/07 09:02:17 tb Exp $ */ | 1 | /* $OpenBSD: bss_mem.c,v 1.19 2022/02/18 17:30:13 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -57,6 +57,7 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | #include <errno.h> | 59 | #include <errno.h> |
60 | #include <limits.h> | ||
60 | #include <stdio.h> | 61 | #include <stdio.h> |
61 | #include <string.h> | 62 | #include <string.h> |
62 | 63 | ||
@@ -66,13 +67,13 @@ | |||
66 | 67 | ||
67 | #include "bio_local.h" | 68 | #include "bio_local.h" |
68 | 69 | ||
69 | static int mem_write(BIO *h, const char *buf, int num); | 70 | static int mem_new(BIO *bio); |
70 | static int mem_read(BIO *h, char *buf, int size); | 71 | static int mem_free(BIO *bio); |
71 | static int mem_puts(BIO *h, const char *str); | 72 | static int mem_write(BIO *bio, const char *in, int in_len); |
72 | static int mem_gets(BIO *h, char *str, int size); | 73 | static int mem_read(BIO *bio, char *out, int out_len); |
73 | static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2); | 74 | static int mem_puts(BIO *bio, const char *in); |
74 | static int mem_new(BIO *h); | 75 | static int mem_gets(BIO *bio, char *out, int out_len); |
75 | static int mem_free(BIO *data); | 76 | static long mem_ctrl(BIO *bio, int cmd, long arg1, void *arg2); |
76 | 77 | ||
77 | static const BIO_METHOD mem_method = { | 78 | static const BIO_METHOD mem_method = { |
78 | .type = BIO_TYPE_MEM, | 79 | .type = BIO_TYPE_MEM, |
@@ -86,137 +87,157 @@ static const BIO_METHOD mem_method = { | |||
86 | .destroy = mem_free | 87 | .destroy = mem_free |
87 | }; | 88 | }; |
88 | 89 | ||
89 | /* bio->num is used to hold the value to return on 'empty', if it is | 90 | /* |
90 | * 0, should_retry is not set */ | 91 | * bio->num is used to hold the value to return on 'empty', if it is |
92 | * 0, should_retry is not set. | ||
93 | */ | ||
91 | 94 | ||
92 | const BIO_METHOD * | 95 | const BIO_METHOD * |
93 | BIO_s_mem(void) | 96 | BIO_s_mem(void) |
94 | { | 97 | { |
95 | return (&mem_method); | 98 | return &mem_method; |
96 | } | 99 | } |
97 | 100 | ||
98 | BIO * | 101 | BIO * |
99 | BIO_new_mem_buf(const void *buf, int len) | 102 | BIO_new_mem_buf(const void *buf, int buf_len) |
100 | { | 103 | { |
101 | BIO *ret; | 104 | BIO *bio; |
102 | BUF_MEM *b; | 105 | BUF_MEM *b; |
103 | size_t sz; | ||
104 | 106 | ||
105 | if (!buf) { | 107 | if (buf == NULL) { |
106 | BIOerror(BIO_R_NULL_PARAMETER); | 108 | BIOerror(BIO_R_NULL_PARAMETER); |
107 | return NULL; | 109 | return NULL; |
108 | } | 110 | } |
109 | sz = (len < 0) ? strlen(buf) : (size_t)len; | 111 | if (buf_len == -1) |
110 | if (!(ret = BIO_new(BIO_s_mem()))) | 112 | buf_len = strlen(buf); |
113 | if (buf_len < 0) { | ||
114 | BIOerror(BIO_R_INVALID_ARGUMENT); | ||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | if ((bio = BIO_new(BIO_s_mem())) == NULL) | ||
111 | return NULL; | 119 | return NULL; |
112 | b = (BUF_MEM *)ret->ptr; | 120 | |
121 | b = bio->ptr; | ||
113 | b->data = (void *)buf; /* Trust in the BIO_FLAGS_MEM_RDONLY flag. */ | 122 | b->data = (void *)buf; /* Trust in the BIO_FLAGS_MEM_RDONLY flag. */ |
114 | b->length = sz; | 123 | b->length = buf_len; |
115 | b->max = sz; | 124 | b->max = buf_len; |
116 | ret->flags |= BIO_FLAGS_MEM_RDONLY; | 125 | bio->flags |= BIO_FLAGS_MEM_RDONLY; |
117 | /* Since this is static data retrying wont help */ | 126 | /* Since this is static data retrying will not help. */ |
118 | ret->num = 0; | 127 | bio->num = 0; |
119 | return ret; | 128 | |
129 | return bio; | ||
120 | } | 130 | } |
121 | 131 | ||
122 | static int | 132 | static int |
123 | mem_new(BIO *bi) | 133 | mem_new(BIO *bio) |
124 | { | 134 | { |
125 | BUF_MEM *b; | 135 | BUF_MEM *b; |
126 | 136 | ||
127 | if ((b = BUF_MEM_new()) == NULL) | 137 | if ((b = BUF_MEM_new()) == NULL) |
128 | return (0); | 138 | return 0; |
129 | bi->shutdown = 1; | 139 | |
130 | bi->init = 1; | 140 | bio->shutdown = 1; |
131 | bi->num = -1; | 141 | bio->init = 1; |
132 | bi->ptr = (char *)b; | 142 | bio->num = -1; |
133 | return (1); | 143 | bio->ptr = b; |
144 | |||
145 | return 1; | ||
134 | } | 146 | } |
135 | 147 | ||
136 | static int | 148 | static int |
137 | mem_free(BIO *a) | 149 | mem_free(BIO *bio) |
138 | { | 150 | { |
139 | if (a == NULL) | 151 | BUF_MEM *b; |
140 | return (0); | 152 | |
141 | if (a->shutdown) { | 153 | if (bio == NULL) |
142 | if ((a->init) && (a->ptr != NULL)) { | 154 | return 0; |
143 | BUF_MEM *b; | 155 | if (!bio->shutdown || !bio->init || bio->ptr == NULL) |
144 | b = (BUF_MEM *)a->ptr; | 156 | return 1; |
145 | if (a->flags & BIO_FLAGS_MEM_RDONLY) | 157 | |
146 | b->data = NULL; | 158 | b = bio->ptr; |
147 | BUF_MEM_free(b); | 159 | if (bio->flags & BIO_FLAGS_MEM_RDONLY) |
148 | a->ptr = NULL; | 160 | b->data = NULL; |
149 | } | 161 | BUF_MEM_free(b); |
150 | } | 162 | bio->ptr = NULL; |
151 | return (1); | 163 | |
164 | return 1; | ||
152 | } | 165 | } |
153 | 166 | ||
154 | static int | 167 | static int |
155 | mem_read(BIO *b, char *out, int outl) | 168 | mem_read(BIO *bio, char *out, int out_len) |
156 | { | 169 | { |
157 | int ret = -1; | 170 | BUF_MEM *bm = bio->ptr; |
158 | BUF_MEM *bm; | 171 | |
159 | 172 | BIO_clear_retry_flags(bio); | |
160 | bm = (BUF_MEM *)b->ptr; | 173 | |
161 | BIO_clear_retry_flags(b); | 174 | if (out == NULL || out_len <= 0) |
162 | ret = (outl >=0 && (size_t)outl > bm->length) ? (int)bm->length : outl; | 175 | return 0; |
163 | if ((out != NULL) && (ret > 0)) { | 176 | |
164 | memcpy(out, bm->data, ret); | 177 | if ((size_t)out_len > bm->length) |
165 | bm->length -= ret; | 178 | out_len = bm->length; |
166 | if (b->flags & BIO_FLAGS_MEM_RDONLY) | 179 | |
167 | bm->data += ret; | 180 | if (out_len == 0) { |
168 | else { | 181 | if (bio->num != 0) |
169 | memmove(&(bm->data[0]), &(bm->data[ret]), bm->length); | 182 | BIO_set_retry_read(bio); |
170 | } | 183 | return bio->num; |
171 | } else if (bm->length == 0) { | ||
172 | ret = b->num; | ||
173 | if (ret != 0) | ||
174 | BIO_set_retry_read(b); | ||
175 | } | 184 | } |
176 | return (ret); | 185 | |
186 | memcpy(out, bm->data, out_len); | ||
187 | bm->length -= out_len; | ||
188 | if (bio->flags & BIO_FLAGS_MEM_RDONLY) { | ||
189 | bm->data += out_len; | ||
190 | } else { | ||
191 | memmove(&(bm->data[0]), &(bm->data[out_len]), | ||
192 | bm->length); | ||
193 | } | ||
194 | return out_len; | ||
177 | } | 195 | } |
178 | 196 | ||
179 | static int | 197 | static int |
180 | mem_write(BIO *b, const char *in, int inl) | 198 | mem_write(BIO *bio, const char *in, int in_len) |
181 | { | 199 | { |
182 | int ret = -1; | 200 | BUF_MEM *bm = bio->ptr; |
183 | int blen; | 201 | size_t buf_len; |
184 | BUF_MEM *bm; | ||
185 | 202 | ||
186 | bm = (BUF_MEM *)b->ptr; | 203 | BIO_clear_retry_flags(bio); |
187 | if (in == NULL) { | 204 | |
188 | BIOerror(BIO_R_NULL_PARAMETER); | 205 | if (in == NULL || in_len <= 0) |
189 | goto end; | 206 | return 0; |
190 | } | ||
191 | 207 | ||
192 | if (b->flags & BIO_FLAGS_MEM_RDONLY) { | 208 | if (bio->flags & BIO_FLAGS_MEM_RDONLY) { |
193 | BIOerror(BIO_R_WRITE_TO_READ_ONLY_BIO); | 209 | BIOerror(BIO_R_WRITE_TO_READ_ONLY_BIO); |
194 | goto end; | 210 | return -1; |
195 | } | 211 | } |
196 | 212 | ||
197 | BIO_clear_retry_flags(b); | 213 | /* |
198 | blen = bm->length; | 214 | * Check for overflow and ensure we do not exceed an int, otherwise we |
199 | if (BUF_MEM_grow_clean(bm, blen + inl) != (blen + inl)) | 215 | * cannot tell if BUF_MEM_grow_clean() succeeded. |
200 | goto end; | 216 | */ |
201 | memcpy(&(bm->data[blen]), in, inl); | 217 | buf_len = bm->length + in_len; |
202 | ret = inl; | 218 | if (buf_len < bm->length || buf_len > INT_MAX) |
203 | end: | 219 | return -1; |
204 | return (ret); | 220 | |
221 | if (BUF_MEM_grow_clean(bm, buf_len) != buf_len) | ||
222 | return -1; | ||
223 | |||
224 | memcpy(&bm->data[buf_len - in_len], in, in_len); | ||
225 | |||
226 | return in_len; | ||
205 | } | 227 | } |
206 | 228 | ||
207 | static long | 229 | static long |
208 | mem_ctrl(BIO *b, int cmd, long num, void *ptr) | 230 | mem_ctrl(BIO *bio, int cmd, long num, void *ptr) |
209 | { | 231 | { |
232 | BUF_MEM *bm = bio->ptr; | ||
210 | long ret = 1; | 233 | long ret = 1; |
211 | char **pptr; | 234 | char **pptr; |
212 | 235 | ||
213 | BUF_MEM *bm = (BUF_MEM *)b->ptr; | ||
214 | |||
215 | switch (cmd) { | 236 | switch (cmd) { |
216 | case BIO_CTRL_RESET: | 237 | case BIO_CTRL_RESET: |
217 | if (bm->data != NULL) { | 238 | if (bm->data != NULL) { |
218 | /* For read only case reset to the start again */ | 239 | /* For read only case reset to the start again */ |
219 | if (b->flags & BIO_FLAGS_MEM_RDONLY) { | 240 | if (bio->flags & BIO_FLAGS_MEM_RDONLY) { |
220 | bm->data -= bm->max - bm->length; | 241 | bm->data -= bm->max - bm->length; |
221 | bm->length = bm->max; | 242 | bm->length = bm->max; |
222 | } else { | 243 | } else { |
@@ -229,19 +250,19 @@ mem_ctrl(BIO *b, int cmd, long num, void *ptr) | |||
229 | ret = (long)(bm->length == 0); | 250 | ret = (long)(bm->length == 0); |
230 | break; | 251 | break; |
231 | case BIO_C_SET_BUF_MEM_EOF_RETURN: | 252 | case BIO_C_SET_BUF_MEM_EOF_RETURN: |
232 | b->num = (int)num; | 253 | bio->num = (int)num; |
233 | break; | 254 | break; |
234 | case BIO_CTRL_INFO: | 255 | case BIO_CTRL_INFO: |
235 | ret = (long)bm->length; | ||
236 | if (ptr != NULL) { | 256 | if (ptr != NULL) { |
237 | pptr = (char **)ptr; | 257 | pptr = (char **)ptr; |
238 | *pptr = (char *)&(bm->data[0]); | 258 | *pptr = (char *)bm->data; |
239 | } | 259 | } |
260 | ret = (long)bm->length; | ||
240 | break; | 261 | break; |
241 | case BIO_C_SET_BUF_MEM: | 262 | case BIO_C_SET_BUF_MEM: |
242 | mem_free(b); | 263 | mem_free(bio); |
243 | b->shutdown = (int)num; | 264 | bio->shutdown = (int)num; |
244 | b->ptr = ptr; | 265 | bio->ptr = ptr; |
245 | break; | 266 | break; |
246 | case BIO_C_GET_BUF_MEM_PTR: | 267 | case BIO_C_GET_BUF_MEM_PTR: |
247 | if (ptr != NULL) { | 268 | if (ptr != NULL) { |
@@ -250,12 +271,11 @@ mem_ctrl(BIO *b, int cmd, long num, void *ptr) | |||
250 | } | 271 | } |
251 | break; | 272 | break; |
252 | case BIO_CTRL_GET_CLOSE: | 273 | case BIO_CTRL_GET_CLOSE: |
253 | ret = (long)b->shutdown; | 274 | ret = (long)bio->shutdown; |
254 | break; | 275 | break; |
255 | case BIO_CTRL_SET_CLOSE: | 276 | case BIO_CTRL_SET_CLOSE: |
256 | b->shutdown = (int)num; | 277 | bio->shutdown = (int)num; |
257 | break; | 278 | break; |
258 | |||
259 | case BIO_CTRL_WPENDING: | 279 | case BIO_CTRL_WPENDING: |
260 | ret = 0L; | 280 | ret = 0L; |
261 | break; | 281 | break; |
@@ -272,27 +292,29 @@ mem_ctrl(BIO *b, int cmd, long num, void *ptr) | |||
272 | ret = 0; | 292 | ret = 0; |
273 | break; | 293 | break; |
274 | } | 294 | } |
275 | return (ret); | 295 | return ret; |
276 | } | 296 | } |
277 | 297 | ||
278 | static int | 298 | static int |
279 | mem_gets(BIO *bp, char *buf, int size) | 299 | mem_gets(BIO *bio, char *out, int out_len) |
280 | { | 300 | { |
281 | int i, j; | 301 | BUF_MEM *bm = bio->ptr; |
282 | int ret = -1; | 302 | int i, out_max; |
283 | char *p; | 303 | char *p; |
284 | BUF_MEM *bm = (BUF_MEM *)bp->ptr; | 304 | int ret = -1; |
285 | 305 | ||
286 | BIO_clear_retry_flags(bp); | 306 | BIO_clear_retry_flags(bio); |
287 | j = bm->length; | 307 | |
288 | if ((size - 1) < j) | 308 | out_max = bm->length; |
289 | j = size - 1; | 309 | if (out_len - 1 < out_max) |
290 | if (j <= 0) { | 310 | out_max = out_len - 1; |
291 | *buf = '\0'; | 311 | if (out_max <= 0) { |
312 | *out = '\0'; | ||
292 | return 0; | 313 | return 0; |
293 | } | 314 | } |
315 | |||
294 | p = bm->data; | 316 | p = bm->data; |
295 | for (i = 0; i < j; i++) { | 317 | for (i = 0; i < out_max; i++) { |
296 | if (p[i] == '\n') { | 318 | if (p[i] == '\n') { |
297 | i++; | 319 | i++; |
298 | break; | 320 | break; |
@@ -300,24 +322,17 @@ mem_gets(BIO *bp, char *buf, int size) | |||
300 | } | 322 | } |
301 | 323 | ||
302 | /* | 324 | /* |
303 | * i is now the max num of bytes to copy, either j or up to | 325 | * i is now the max num of bytes to copy, either out_max or up to and |
304 | * and including the first newline | 326 | * including the first newline |
305 | */ | 327 | */ |
328 | if ((ret = mem_read(bio, out, i)) > 0) | ||
329 | out[ret] = '\0'; | ||
306 | 330 | ||
307 | i = mem_read(bp, buf, i); | 331 | return ret; |
308 | if (i > 0) | ||
309 | buf[i] = '\0'; | ||
310 | ret = i; | ||
311 | return (ret); | ||
312 | } | 332 | } |
313 | 333 | ||
314 | static int | 334 | static int |
315 | mem_puts(BIO *bp, const char *str) | 335 | mem_puts(BIO *bio, const char *in) |
316 | { | 336 | { |
317 | int n, ret; | 337 | return mem_write(bio, in, strlen(in)); |
318 | |||
319 | n = strlen(str); | ||
320 | ret = mem_write(bp, str, n); | ||
321 | /* memory semantics is that it will always work */ | ||
322 | return (ret); | ||
323 | } | 338 | } |