~ubuntu-branches/ubuntu/wily/freerdp/wily-proposed

« back to all changes in this revision

Viewing changes to asn1/ber_decoder.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Jeremy Bicha, Jean-Louis Dupond, Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120131100214-jaok3uwvni7sqxth
Tags: 1.0.0-0git1
Upload current Debian packaging git to get this rolling for precise.

[ Jeremy Bicha ]
* New upstream release. Closes: #647498.
* Updated symbols and bumped soname
* debian/control:
  - Added new build dependencies
  - Bump Standards-Version to 3.9.2
* debian/source/format: Set to 3.0 (quilt)
* debian/rules: Turn on strict symbols checking
* debian/watch: Watch github

[ Jean-Louis Dupond ]
* debian/control: Updated homepage
* debian/copyright: Reflect upstream switch to the Apache license

[ Martin Pitt ]
* debian/libfreerdp0.symbols: Fix version number, should
  be 1.0~beta5, not 1.0-beta5.
* debian/control: Add libavcodec-dev build dependency, upstream build system
  checks for that. Thanks Jean-Louis Dupond!

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*-
2
 
 * Copyright (c) 2003, 2004 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
 
#undef  ADVANCE
8
 
#define ADVANCE(num_bytes)      do {                                    \
9
 
                size_t num = num_bytes;                                 \
10
 
                ptr = ((const char *)ptr) + num;                        \
11
 
                size -= num;                                            \
12
 
                consumed_myself += num;                                 \
13
 
        } while(0)
14
 
#undef  RETURN
15
 
#define RETURN(_code)   do {                                            \
16
 
                asn_dec_rval_t rval;                                    \
17
 
                rval.code = _code;                                      \
18
 
                if(opt_ctx) opt_ctx->step = step; /* Save context */    \
19
 
                if(_code == RC_OK || opt_ctx)                           \
20
 
                        rval.consumed = consumed_myself;                \
21
 
                else                                                    \
22
 
                        rval.consumed = 0;      /* Context-free */      \
23
 
                return rval;                                            \
24
 
        } while(0)
25
 
 
26
 
/*
27
 
 * The BER decoder of any type.
28
 
 */
29
 
asn_dec_rval_t
30
 
ber_decode(asn_codec_ctx_t *opt_codec_ctx,
31
 
        asn_TYPE_descriptor_t *type_descriptor,
32
 
        void **struct_ptr, const void *ptr, size_t size) {
33
 
        asn_codec_ctx_t s_codec_ctx;
34
 
 
35
 
        /*
36
 
         * Stack checker requires that the codec context
37
 
         * must be allocated on the stack.
38
 
         */
39
 
        if(opt_codec_ctx) {
40
 
                if(opt_codec_ctx->max_stack_size) {
41
 
                        s_codec_ctx = *opt_codec_ctx;
42
 
                        opt_codec_ctx = &s_codec_ctx;
43
 
                }
44
 
        } else {
45
 
                /* If context is not given, be security-conscious anyway */
46
 
                memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
47
 
                s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
48
 
                opt_codec_ctx = &s_codec_ctx;
49
 
        }
50
 
 
51
 
        /*
52
 
         * Invoke type-specific decoder.
53
 
         */
54
 
        return type_descriptor->ber_decoder(opt_codec_ctx, type_descriptor,
55
 
                struct_ptr,     /* Pointer to the destination structure */
56
 
                ptr, size,      /* Buffer and its size */
57
 
                0               /* Default tag mode is 0 */
58
 
                );
59
 
}
60
 
 
61
 
/*
62
 
 * Check the set of <TL<TL<TL...>>> tags matches the definition.
63
 
 */
64
 
asn_dec_rval_t
65
 
ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
66
 
                asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx,
67
 
                const void *ptr, size_t size, int tag_mode, int last_tag_form,
68
 
                ber_tlv_len_t *last_length, int *opt_tlv_form) {
69
 
        ssize_t consumed_myself = 0;
70
 
        ssize_t tag_len;
71
 
        ssize_t len_len;
72
 
        ber_tlv_tag_t tlv_tag;
73
 
        ber_tlv_len_t tlv_len;
74
 
        ber_tlv_len_t limit_len = -1;
75
 
        int expect_00_terminators = 0;
76
 
        int tlv_constr = -1;    /* If CHOICE, opt_tlv_form is not given */
77
 
        int step = opt_ctx ? opt_ctx->step : 0; /* Where we left previously */
78
 
        int tagno;
79
 
 
80
 
        /*
81
 
         * Make sure we didn't exceed the maximum stack size.
82
 
         */
83
 
        if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
84
 
                RETURN(RC_FAIL);
85
 
 
86
 
        /*
87
 
         * So what does all this implicit skip stuff mean?
88
 
         * Imagine two types,
89
 
         *      A ::= [5] IMPLICIT      T
90
 
         *      B ::= [2] EXPLICIT      T
91
 
         * Where T is defined as
92
 
         *      T ::= [4] IMPLICIT SEQUENCE { ... }
93
 
         * 
94
 
         * Let's say, we are starting to decode type A, given the
95
 
         * following TLV stream: <5> <0>. What does this mean?
96
 
         * It means that the type A contains type T which is,
97
 
         * in turn, empty.
98
 
         * Remember though, that we are still in A. We cannot
99
 
         * just pass control to the type T decoder. Why? Because
100
 
         * the type T decoder expects <4> <0>, not <5> <0>.
101
 
         * So, we must make sure we are going to receive <5> while
102
 
         * still in A, then pass control to the T decoder, indicating
103
 
         * that the tag <4> was implicitly skipped. The decoder of T
104
 
         * hence will be prepared to treat <4> as valid tag, and decode
105
 
         * it appropriately.
106
 
         */
107
 
 
108
 
        tagno = step    /* Continuing where left previously */
109
 
                + (tag_mode==1?-1:0)
110
 
                ;
111
 
        ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)",
112
 
                td->name, (long)size, tag_mode, step, tagno);
113
 
        /* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */
114
 
 
115
 
        if(tag_mode == 0 && tagno == td->tags_count) {
116
 
                /*
117
 
                 * This must be the _untagged_ ANY type,
118
 
                 * which outermost tag isn't known in advance.
119
 
                 * Fetch the tag and length separately.
120
 
                 */
121
 
                tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
122
 
                switch(tag_len) {
123
 
                case -1: RETURN(RC_FAIL);
124
 
                case 0: RETURN(RC_WMORE);
125
 
                }
126
 
                tlv_constr = BER_TLV_CONSTRUCTED(ptr);
127
 
                len_len = ber_fetch_length(tlv_constr,
128
 
                        (const char *)ptr + tag_len, size - tag_len, &tlv_len);
129
 
                switch(len_len) {
130
 
                case -1: RETURN(RC_FAIL);
131
 
                case 0: RETURN(RC_WMORE);
132
 
                }
133
 
                ASN_DEBUG("Advancing %ld in ANY case",
134
 
                        (long)(tag_len + len_len));
135
 
                ADVANCE(tag_len + len_len);
136
 
        } else {
137
 
                assert(tagno < td->tags_count); /* At least one loop */
138
 
        }
139
 
        for((void)tagno; tagno < td->tags_count; tagno++, step++) {
140
 
 
141
 
                /*
142
 
                 * Fetch and process T from TLV.
143
 
                 */
144
 
                tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
145
 
                        ASN_DEBUG("Fetching tag from {%p,%ld}: "
146
 
                                "len %ld, step %d, tagno %d got %s",
147
 
                                ptr, (long)size,
148
 
                                (long)tag_len, step, tagno,
149
 
                                ber_tlv_tag_string(tlv_tag));
150
 
                switch(tag_len) {
151
 
                case -1: RETURN(RC_FAIL);
152
 
                case 0: RETURN(RC_WMORE);
153
 
                }
154
 
 
155
 
                tlv_constr = BER_TLV_CONSTRUCTED(ptr);
156
 
 
157
 
                /*
158
 
                 * If {I}, don't check anything.
159
 
                 * If {I,B,C}, check B and C unless we're at I.
160
 
                 */
161
 
                if(tag_mode != 0 && step == 0) {
162
 
                        /*
163
 
                         * We don't expect tag to match here.
164
 
                         * It's just because we don't know how the tag
165
 
                         * is supposed to look like.
166
 
                         */
167
 
                } else {
168
 
                    assert(tagno >= 0); /* Guaranteed by the code above */
169
 
                    if(tlv_tag != td->tags[tagno]) {
170
 
                        /*
171
 
                         * Unexpected tag. Too bad.
172
 
                         */
173
 
                        ASN_DEBUG("Expected: %s, "
174
 
                                "expectation failed (tn=%d, tm=%d)",
175
 
                                ber_tlv_tag_string(td->tags[tagno]),
176
 
                                tagno, tag_mode
177
 
                        );
178
 
                        RETURN(RC_FAIL);
179
 
                    }
180
 
                }
181
 
 
182
 
                /*
183
 
                 * Attention: if there are more tags expected,
184
 
                 * ensure that the current tag is presented
185
 
                 * in constructed form (it contains other tags!).
186
 
                 * If this one is the last one, check that the tag form
187
 
                 * matches the one given in descriptor.
188
 
                 */
189
 
                if(tagno < (td->tags_count - 1)) {
190
 
                        if(tlv_constr == 0) {
191
 
                                ASN_DEBUG("tlv_constr = %d, expfail",
192
 
                                        tlv_constr);
193
 
                                RETURN(RC_FAIL);
194
 
                        }
195
 
                } else {
196
 
                        if(last_tag_form != tlv_constr
197
 
                        && last_tag_form != -1) {
198
 
                                ASN_DEBUG("last_tag_form %d != %d",
199
 
                                        last_tag_form, tlv_constr);
200
 
                                RETURN(RC_FAIL);
201
 
                        }
202
 
                }
203
 
 
204
 
                /*
205
 
                 * Fetch and process L from TLV.
206
 
                 */
207
 
                len_len = ber_fetch_length(tlv_constr,
208
 
                        (const char *)ptr + tag_len, size - tag_len, &tlv_len);
209
 
                ASN_DEBUG("Fetchinig len = %ld", (long)len_len);
210
 
                switch(len_len) {
211
 
                case -1: RETURN(RC_FAIL);
212
 
                case 0: RETURN(RC_WMORE);
213
 
                }
214
 
 
215
 
                /*
216
 
                 * FIXME
217
 
                 * As of today, the chain of tags
218
 
                 * must either contain several indefinite length TLVs,
219
 
                 * or several definite length ones.
220
 
                 * No mixing is allowed.
221
 
                 */
222
 
                if(tlv_len == -1) {
223
 
                        /*
224
 
                         * Indefinite length.
225
 
                         */
226
 
                        if(limit_len == -1) {
227
 
                                expect_00_terminators++;
228
 
                        } else {
229
 
                                ASN_DEBUG("Unexpected indefinite length "
230
 
                                        "in a chain of definite lengths");
231
 
                                RETURN(RC_FAIL);
232
 
                        }
233
 
                        ADVANCE(tag_len + len_len);
234
 
                        continue;
235
 
                } else {
236
 
                        if(expect_00_terminators) {
237
 
                                ASN_DEBUG("Unexpected definite length "
238
 
                                        "in a chain of indefinite lengths");
239
 
                                RETURN(RC_FAIL);
240
 
                        }
241
 
                }
242
 
 
243
 
                /*
244
 
                 * Check that multiple TLVs specify ever decreasing length,
245
 
                 * which is consistent.
246
 
                 */
247
 
                if(limit_len == -1) {
248
 
                        limit_len    = tlv_len + tag_len + len_len;
249
 
                        if(limit_len < 0) {
250
 
                                /* Too great tlv_len value? */
251
 
                                RETURN(RC_FAIL);
252
 
                        }
253
 
                } else if(limit_len != tlv_len + tag_len + len_len) {
254
 
                        /*
255
 
                         * Inner TLV specifies length which is inconsistent
256
 
                         * with the outer TLV's length value.
257
 
                         */
258
 
                        ASN_DEBUG("Outer TLV is %ld and inner is %ld",
259
 
                                (long)limit_len, (long)tlv_len);
260
 
                        RETURN(RC_FAIL);
261
 
                }
262
 
 
263
 
                ADVANCE(tag_len + len_len);
264
 
 
265
 
                limit_len -= (tag_len + len_len);
266
 
                if((ssize_t)size > limit_len) {
267
 
                        /*
268
 
                         * Make sure that we won't consume more bytes
269
 
                         * from the parent frame than the inferred limit.
270
 
                         */
271
 
                        size = limit_len;
272
 
                }
273
 
        }
274
 
 
275
 
        if(opt_tlv_form)
276
 
                *opt_tlv_form = tlv_constr;
277
 
        if(expect_00_terminators)
278
 
                *last_length = -expect_00_terminators;
279
 
        else
280
 
                *last_length = tlv_len;
281
 
 
282
 
        RETURN(RC_OK);
283
 
}