Lev Walkin | e7b73c4 | 2017-07-07 10:06:17 -0700 | [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 | |
| 7 | /* |
| 8 | * The OER decoder of any type. |
| 9 | */ |
| 10 | asn_dec_rval_t |
Lev Walkin | afbf2a9 | 2017-09-12 23:30:27 -0700 | [diff] [blame] | 11 | oer_decode(const asn_codec_ctx_t *opt_codec_ctx, |
Lev Walkin | e7b73c4 | 2017-07-07 10:06:17 -0700 | [diff] [blame] | 12 | asn_TYPE_descriptor_t *type_descriptor, |
| 13 | void **struct_ptr, const void *ptr, size_t size) { |
| 14 | asn_codec_ctx_t s_codec_ctx; |
| 15 | |
| 16 | /* |
| 17 | * Stack checker requires that the codec context |
| 18 | * must be allocated on the stack. |
| 19 | */ |
| 20 | if(opt_codec_ctx) { |
| 21 | if(opt_codec_ctx->max_stack_size) { |
| 22 | s_codec_ctx = *opt_codec_ctx; |
| 23 | opt_codec_ctx = &s_codec_ctx; |
| 24 | } |
| 25 | } else { |
| 26 | /* If context is not given, be security-conscious anyway */ |
| 27 | memset(&s_codec_ctx, 0, sizeof(s_codec_ctx)); |
| 28 | s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX; |
| 29 | opt_codec_ctx = &s_codec_ctx; |
| 30 | } |
| 31 | |
| 32 | /* |
| 33 | * Invoke type-specific decoder. |
| 34 | */ |
Bi-Ruei, Chiu | 1f87ac0 | 2017-08-20 01:25:45 +0800 | [diff] [blame] | 35 | return type_descriptor->op->oer_decoder(opt_codec_ctx, type_descriptor, 0, |
Lev Walkin | e7b73c4 | 2017-07-07 10:06:17 -0700 | [diff] [blame] | 36 | struct_ptr, /* Pointer to the destination structure */ |
| 37 | ptr, size /* Buffer and its size */ |
| 38 | ); |
| 39 | } |
Lev Walkin | 20ea852 | 2017-07-20 14:52:02 +0300 | [diff] [blame] | 40 | |
| 41 | /* |
| 42 | * Open Type is encoded as a length (#8.6) followed by that number of bytes. |
| 43 | * Since we're just skipping, reading the length would be enough. |
| 44 | */ |
| 45 | ssize_t |
| 46 | oer_open_type_skip(const void *bufptr, size_t size) { |
| 47 | size_t len = 0; |
| 48 | return oer_fetch_length(bufptr, size, &len); |
| 49 | } |
| 50 | |
| 51 | /* |
| 52 | * Read the Open Type (X.696 (08/2015), #30). |
| 53 | * RETURN VALUES: |
| 54 | * 0: More data expected than bufptr contains. |
| 55 | * -1: Fatal error deciphering length. |
| 56 | * >0: Number of bytes used from bufptr. |
| 57 | */ |
| 58 | ssize_t |
Lev Walkin | afbf2a9 | 2017-09-12 23:30:27 -0700 | [diff] [blame] | 59 | oer_open_type_get(const asn_codec_ctx_t *opt_codec_ctx, |
Lev Walkin | 20ea852 | 2017-07-20 14:52:02 +0300 | [diff] [blame] | 60 | struct asn_TYPE_descriptor_s *td, |
| 61 | asn_oer_constraints_t *constraints, void **struct_ptr, |
| 62 | const void *bufptr, size_t size) { |
| 63 | |
| 64 | asn_dec_rval_t dr; |
| 65 | size_t container_len = 0; |
| 66 | ssize_t len_len; |
| 67 | |
| 68 | /* Get the size of a length determinant */ |
| 69 | len_len = oer_fetch_length(bufptr, size, &container_len); |
| 70 | if(len_len <= 0) { |
| 71 | return len_len; /* Error or more data expected */ |
| 72 | } |
| 73 | |
| 74 | /* |
| 75 | * len_len can't be bigger than size, but size without len_len |
| 76 | * should be bigger or equal to container length |
| 77 | */ |
| 78 | if(size - len_len < container_len) { |
| 79 | /* More data is expected */ |
| 80 | return 0; |
| 81 | } |
| 82 | |
Bi-Ruei, Chiu | 1f87ac0 | 2017-08-20 01:25:45 +0800 | [diff] [blame] | 83 | dr = td->op->oer_decoder(opt_codec_ctx, td, constraints, struct_ptr, |
Lev Walkin | 20ea852 | 2017-07-20 14:52:02 +0300 | [diff] [blame] | 84 | (const uint8_t *)bufptr + len_len, container_len); |
| 85 | if(dr.code == RC_OK) { |
| 86 | return len_len + container_len; |
| 87 | } else { |
| 88 | /* Even if RC_WMORE, we can't get more data into a closed container. */ |
| 89 | ASN_STRUCT_FREE(*td, *struct_ptr); |
| 90 | *struct_ptr = 0; |
| 91 | return -1; |
| 92 | } |
| 93 | } |
| 94 | |