Fixed serious bug in odr_cons
[yaz-moved-to-github.git] / odr / odr_cons.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: odr_cons.c,v $
7  * Revision 1.8  1995-03-15 11:18:04  quinn
8  * Fixed serious bug in odr_cons
9  *
10  * Revision 1.7  1995/03/10  11:44:41  quinn
11  * Fixed serious stack-bug in odr_cons_begin
12  *
13  * Revision 1.6  1995/03/08  12:12:23  quinn
14  * Added better error checking.
15  *
16  * Revision 1.5  1995/02/10  18:57:25  quinn
17  * More in the way of error-checking.
18  *
19  * Revision 1.4  1995/02/10  15:55:29  quinn
20  * Bug fixes, mostly.
21  *
22  * Revision 1.3  1995/02/09  15:51:48  quinn
23  * Works better now.
24  *
25  * Revision 1.2  1995/02/07  17:52:59  quinn
26  * A damn mess, but now things work, I think.
27  *
28  * Revision 1.1  1995/02/02  16:21:53  quinn
29  * First kick.
30  *
31  */
32
33 #include <odr.h>
34
35 int odr_constructed_begin(ODR o, void *p, int class, int tag)
36 {
37     int res;
38     int cons = 1;
39
40     if (o->error)
41         return 0;
42     if (o->t_class < 0)
43     {
44         o->t_class = class;
45         o->t_tag = tag;
46     }
47     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, 1)) < 0)
48         return 0;
49     if (!res || !cons)
50         return 0;
51
52     if (o->stackp == ODR_MAX_STACK - 1)
53     {
54         o->error = OSTACK;
55         return 0;
56     }
57     o->stack[++(o->stackp)].lenb = o->bp;
58 #ifdef ODR_DEBUG
59     fprintf(stderr, "[cons_begin(%d)]", o->stackp);
60 #endif
61     if (o->direction == ODR_ENCODE || o->direction == ODR_PRINT)
62     {
63         o->stack[o->stackp].lenlen = 1;
64         o->bp++;
65         o->left--;
66     }
67     else if (o->direction == ODR_DECODE)
68     {
69         if ((res = ber_declen(o->bp, &o->stack[o->stackp].len)) < 0)
70             return 0;
71         o->stack[o->stackp].lenlen = res;
72         o->bp += res;
73         o->left -= res;
74     }
75     else return 0;
76
77     o->stack[o->stackp].base = o->bp;
78     return 1;
79 }
80
81 int odr_constructed_more(ODR o)
82 {
83     if (o->error)
84         return 0;
85     if (o->stackp < 0)
86         return 0;
87     if (o->stack[o->stackp].len >= 0)
88         return o->bp - o->stack[o->stackp].base < o->stack[o->stackp].len;
89     else
90         return (!(*o->bp == 0 && *(o->bp + 1) == 0));
91 }
92
93 int odr_constructed_end(ODR o)
94 {
95     int res;
96
97     if (o->error)
98         return 0;
99     if (o->stackp < 0)
100     {
101         o->error = OOTHER;
102         return 0;
103     }
104     switch (o->direction)
105     {
106         case ODR_DECODE:
107             if (o->stack[o->stackp].len < 0)
108             {
109                 if (*o->bp++ == 0 && *(o->bp++) == 0)
110                 {
111                     o->left -= 2;
112                     o->stackp--;
113                     return 1;
114                 }
115                 else
116                 {
117                     o->error = OOTHER;
118                     return 0;
119                 }
120             }
121             else if (o->bp - o->stack[o->stackp].base !=
122                 o->stack[o->stackp].len)
123             {
124                 o->error = OOTHER;
125                 return 0;
126             }
127             o->stackp--;
128             return 1;
129         case ODR_ENCODE:
130             if ((res = ber_enclen(o->stack[o->stackp].lenb,
131                 o->bp - o->stack[o->stackp].base,
132                 o->stack[o->stackp].lenlen, 1)) < 0)
133             {
134                 o->error = OSPACE;
135                 return 0;
136             }
137             if (res == 0)   /* indefinite encoding */
138             {
139 #ifdef ODR_DEBUG
140                 fprintf(stderr, "[cons_end(%d): indefinite]", o->stackp);
141 #endif
142                 *(o->bp++) = 0;
143                 *(o->bp++) = 0;
144                 o->left -= 2;
145             }
146 #ifdef ODR_DEBUG
147             else
148             {
149                 fprintf(stderr, "[cons_end(%d): definite]", o->stackp);
150             }
151 #endif
152             o->stackp--;
153             return 1;
154         case ODR_PRINT: return 1;
155         default:
156             o->error = OOTHER;
157             return 0;
158     }
159 }