Ron Shacham | 0eba05c | 2020-05-08 15:13:19 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved. |
| 3 | * Redistribution and modifications are permitted subject to BSD license. |
| 4 | */ |
| 5 | #include <asn_internal.h> |
| 6 | #include <asn_codecs_prim.h> |
| 7 | |
| 8 | /* |
| 9 | * The OER decoder of any type. |
| 10 | */ |
| 11 | asn_dec_rval_t |
| 12 | oer_decode(const asn_codec_ctx_t *opt_codec_ctx, |
| 13 | const asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr, |
| 14 | const void *ptr, size_t size) { |
| 15 | asn_codec_ctx_t s_codec_ctx; |
| 16 | |
| 17 | /* |
| 18 | * Stack checker requires that the codec context |
| 19 | * must be allocated on the stack. |
| 20 | */ |
| 21 | if(opt_codec_ctx) { |
| 22 | if(opt_codec_ctx->max_stack_size) { |
| 23 | s_codec_ctx = *opt_codec_ctx; |
| 24 | opt_codec_ctx = &s_codec_ctx; |
| 25 | } |
| 26 | } else { |
| 27 | /* If context is not given, be security-conscious anyway */ |
| 28 | memset(&s_codec_ctx, 0, sizeof(s_codec_ctx)); |
| 29 | s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX; |
| 30 | opt_codec_ctx = &s_codec_ctx; |
| 31 | } |
| 32 | |
| 33 | /* |
| 34 | * Invoke type-specific decoder. |
| 35 | */ |
| 36 | return type_descriptor->op->oer_decoder(opt_codec_ctx, type_descriptor, 0, |
| 37 | struct_ptr, /* Pointer to the destination structure */ |
| 38 | ptr, size /* Buffer and its size */ |
| 39 | ); |
| 40 | } |
| 41 | |
| 42 | /* |
| 43 | * Open Type is encoded as a length (#8.6) followed by that number of bytes. |
| 44 | * Since we're just skipping, reading the length would be enough. |
| 45 | */ |
| 46 | ssize_t |
| 47 | oer_open_type_skip(const void *bufptr, size_t size) { |
| 48 | size_t len = 0; |
| 49 | return oer_fetch_length(bufptr, size, &len); |
| 50 | } |
| 51 | |
| 52 | /* |
| 53 | * Read the Open Type (X.696 (08/2015), #30). |
| 54 | * RETURN VALUES: |
| 55 | * 0: More data expected than bufptr contains. |
| 56 | * -1: Fatal error deciphering length. |
| 57 | * >0: Number of bytes used from bufptr. |
| 58 | */ |
| 59 | ssize_t |
| 60 | oer_open_type_get(const asn_codec_ctx_t *opt_codec_ctx, |
| 61 | const struct asn_TYPE_descriptor_s *td, |
| 62 | const asn_oer_constraints_t *constraints, void **struct_ptr, |
| 63 | const void *bufptr, size_t size) { |
| 64 | asn_dec_rval_t dr; |
| 65 | size_t container_len = 0; |
| 66 | ssize_t len_len; |
| 67 | enum asn_struct_free_method dispose_method = |
| 68 | (*struct_ptr) ? ASFM_FREE_UNDERLYING_AND_RESET : ASFM_FREE_EVERYTHING; |
| 69 | |
| 70 | /* Get the size of a length determinant */ |
| 71 | len_len = oer_fetch_length(bufptr, size, &container_len); |
| 72 | if(len_len <= 0) { |
| 73 | return len_len; /* Error or more data expected */ |
| 74 | } |
| 75 | |
| 76 | /* |
| 77 | * len_len can't be bigger than size, but size without len_len |
| 78 | * should be bigger or equal to container length |
| 79 | */ |
| 80 | if(size - len_len < container_len) { |
| 81 | /* More data is expected */ |
| 82 | return 0; |
| 83 | } |
| 84 | |
| 85 | dr = td->op->oer_decoder(opt_codec_ctx, td, constraints, struct_ptr, |
| 86 | (const uint8_t *)bufptr + len_len, container_len); |
| 87 | if(dr.code == RC_OK) { |
| 88 | return len_len + container_len; |
| 89 | } else { |
| 90 | /* Even if RC_WMORE, we can't get more data into a closed container. */ |
| 91 | td->op->free_struct(td, *struct_ptr, dispose_method); |
| 92 | *struct_ptr = NULL; |
| 93 | return -1; |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | |
| 98 | asn_dec_rval_t |
| 99 | oer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx, |
| 100 | const asn_TYPE_descriptor_t *td, |
| 101 | const asn_oer_constraints_t *constraints, void **sptr, |
| 102 | const void *ptr, size_t size) { |
| 103 | ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr; |
| 104 | asn_dec_rval_t rval = {RC_OK, 0}; |
| 105 | size_t expected_length = 0; |
| 106 | ssize_t len_len; |
| 107 | |
| 108 | (void)td; |
| 109 | (void)opt_codec_ctx; |
| 110 | (void)constraints; |
| 111 | |
| 112 | if(!st) { |
| 113 | st = (ASN__PRIMITIVE_TYPE_t *)(*sptr = CALLOC( |
| 114 | 1, sizeof(ASN__PRIMITIVE_TYPE_t))); |
| 115 | if(!st) ASN__DECODE_FAILED; |
| 116 | } |
| 117 | |
| 118 | |
| 119 | /* |
| 120 | * X.696 (08/2015) #27.2 |
| 121 | * Encode length determinant as _number of octets_, but only |
| 122 | * if upper bound is not equal to lower bound. |
| 123 | */ |
| 124 | len_len = oer_fetch_length(ptr, size, &expected_length); |
| 125 | if(len_len > 0) { |
| 126 | rval.consumed = len_len; |
| 127 | ptr = (const char *)ptr + len_len; |
| 128 | size -= len_len; |
| 129 | } else if(len_len == 0) { |
| 130 | ASN__DECODE_STARVED; |
| 131 | } else if(len_len < 0) { |
| 132 | ASN__DECODE_FAILED; |
| 133 | } |
| 134 | |
| 135 | if(size < expected_length) { |
| 136 | ASN__DECODE_STARVED; |
| 137 | } else { |
| 138 | uint8_t *buf = MALLOC(expected_length + 1); |
| 139 | if(buf == NULL) { |
| 140 | ASN__DECODE_FAILED; |
| 141 | } else { |
| 142 | memcpy(buf, ptr, expected_length); |
| 143 | buf[expected_length] = '\0'; |
| 144 | } |
| 145 | FREEMEM(st->buf); |
| 146 | st->buf = buf; |
| 147 | st->size = expected_length; |
| 148 | |
| 149 | rval.consumed += expected_length; |
| 150 | return rval; |
| 151 | } |
| 152 | } |