blob: a606bf9966bad63c3a40e28ec3636d806b51e0e8 [file] [log] [blame]
Lev Walkined3a4ae2017-07-07 10:09:51 -07001/*
2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3 * All rights reserved.
4 * Redistribution and modifications are permitted subject to BSD license.
5 */
6#ifndef ASN_DISABLE_OER_SUPPORT
7
8#include <asn_internal.h>
9#include <INTEGER.h>
10#include <errno.h>
11
12asn_dec_rval_t
13INTEGER_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
14 asn_oer_constraints_t *constraints, void **sptr,
15 const void *ptr, size_t size) {
16 asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
17 asn_dec_rval_t rval = {RC_OK, 0};
18 INTEGER_t *st = (INTEGER_t *)*sptr;
19 asn_oer_constraint_t *ct;
Lev Walkine4d8c922017-07-10 20:29:33 -070020 size_t req_bytes = 0; /* 0 = length determinant is required */
Lev Walkined3a4ae2017-07-07 10:09:51 -070021
22 (void)opt_codec_ctx;
Lev Walkine4d8c922017-07-10 20:29:33 -070023 (void)specs;
Lev Walkined3a4ae2017-07-07 10:09:51 -070024
25 if(!st) {
26 st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
27 if(!st) ASN__DECODE_FAILED;
28 }
29
Lev Walkined3a4ae2017-07-07 10:09:51 -070030 FREEMEM(st->buf);
31 st->buf = 0;
32 st->size = 0;
Lev Walkine4d8c922017-07-10 20:29:33 -070033
34 if(!constraints) constraints = td->oer_constraints;
35 ct = constraints ? &constraints->value : 0;
36
37 if(ct && (ct->flags & AOC_HAS_LOWER_BOUND) && ct->lower_bound >= 0) {
38 /* X.969 08/2015 10.2(a) */
39 unsigned msb; /* Most significant bit */
40 size_t useful_size;
41
42 intmax_t ub = ct->upper_bound;
43 if(ct->flags & AOC_HAS_UPPER_BOUND) {
44 if(ub <= 255) {
45 req_bytes = 1;
46 } else if(ub <= 65535) {
47 req_bytes = 2;
48 } else if(ub <= 4294967295UL) {
49 req_bytes = 4;
50 } else if(ub <= 18446744073709551615ULL) {
51 req_bytes = 8;
52 }
53 }
54
55 if(req_bytes == 0) { /* #8.6, using length determinant */
56 ssize_t consumed = oer_fetch_length(ptr, size, &req_bytes);
57 if(consumed == 0) {
58 ASN__DECODE_STARVED;
59 } else if(consumed == -1) {
60 ASN__DECODE_FAILED;
61 }
62 rval.consumed += consumed;
63 ptr = (const char *)ptr + consumed;
64 size -= consumed;
65 }
66
67 if(req_bytes > size) {
68 ASN__DECODE_STARVED;
69 }
70
71 /* Check most significant bit */
72 msb = *(const uint8_t *)ptr >> 7; /* yields 0 or 1 */
73 useful_size = msb + req_bytes;
74 st->buf = (uint8_t *)MALLOC(useful_size + 1);
75 if(!st->buf) {
76 ASN__DECODE_FAILED;
77 }
78
79 /*
80 * Record a large unsigned in a way not to confuse it
81 * with signed value.
82 */
83 st->buf[0] = '\0';
84 memcpy(st->buf + msb, ptr, req_bytes);
85 st->buf[useful_size] = '\0'; /* Just in case, 0-terminate */
86 st->size = useful_size;
87
88 rval.consumed += req_bytes;
89 return rval;
90 } else if(ct && (ct->flags & AOC_HAS_LOWER_BOUND)) {
91 /* X.969 08/2015 10.2(b) - no lower bound or negative lower bound */
92
93 intmax_t lb = ct->lower_bound;
94 intmax_t ub = ct->upper_bound;
95
96 if(ct->flags & AOC_HAS_UPPER_BOUND) {
97 if(lb >= -128 && ub <= 127) {
98 req_bytes = 1;
99 } else if(lb >= -32768 && ub <= 32767) {
100 req_bytes = 2;
101 } else if(lb >= -2147483648L && ub <= 2147483647L) {
102 req_bytes = 4;
103 } else if(lb >= -9223372036854775808LL
104 && ub <= 9223372036854775807LL) {
105 req_bytes = 8;
106 }
107 }
108 }
109
110 /* No lower bound and no upper bound, effectively */
111
112 if(req_bytes == 0) { /* #8.6, using length determinant */
113 ssize_t consumed = oer_fetch_length(ptr, size, &req_bytes);
114 if(consumed == 0) {
115 ASN__DECODE_STARVED;
116 } else if(consumed == -1) {
117 ASN__DECODE_FAILED;
118 }
119 rval.consumed += consumed;
120 ptr = (const char *)ptr + consumed;
121 size -= consumed;
122 }
123
124 if(req_bytes > size) {
125 ASN__DECODE_STARVED;
126 }
127
128 st->buf = (uint8_t *)MALLOC(req_bytes + 1);
129 if(!st->buf) {
130 ASN__DECODE_FAILED;
131 }
132
133 memcpy(st->buf, ptr, req_bytes);
134 st->buf[req_bytes] = '\0'; /* Just in case, 0-terminate */
135 st->size = req_bytes;
136
137 rval.consumed += req_bytes;
138 return rval;
Lev Walkined3a4ae2017-07-07 10:09:51 -0700139}
140
141#endif /* ASN_DISABLE_OER_SUPPORT */