diff options
| author | jsing <> | 2022-02-18 17:30:13 +0000 |
|---|---|---|
| committer | jsing <> | 2022-02-18 17:30:13 +0000 |
| commit | e7ff7e9be98905e4e791056a5d6ec18f71fc52ff (patch) | |
| tree | b2a0af2ad0615017288f9b467da71f7c2e8ab3c9 /src | |
| parent | 303b9a6be2b1c82c6b6e7c9d259745149c6210de (diff) | |
| download | openbsd-e7ff7e9be98905e4e791056a5d6ec18f71fc52ff.tar.gz openbsd-e7ff7e9be98905e4e791056a5d6ec18f71fc52ff.tar.bz2 openbsd-e7ff7e9be98905e4e791056a5d6ec18f71fc52ff.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')
| -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 | } |
