Fix uninit var in ber_decinteger
[yaz-moved-to-github.git] / src / ber_int.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2009 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /** 
7  * \file ber_int.c
8  * \brief Implements BER INTEGER encoding and decoding.
9  *
10  * This source file implements BER encoding and decoding of
11  * the INTEGER type.
12  */
13
14 #if HAVE_CONFIG_H
15 #include <config.h>
16 #endif
17
18 #include <string.h>
19
20 #if HAVE_SYS_TYPES_H
21 #include <sys/types.h>
22 #endif
23
24 #ifdef WIN32
25 #include <winsock.h>
26 #endif
27
28 #include "odr-priv.h"
29
30 static int ber_encinteger(ODR o, Odr_int val);
31 static int ber_decinteger(const unsigned char *buf, Odr_int *val, int max);
32
33 int ber_integer(ODR o, Odr_int *val)
34 {
35     int res;
36
37     switch (o->direction)
38     {
39     case ODR_DECODE:
40         if ((res = ber_decinteger(o->bp, val, odr_max(o))) <= 0)
41         {
42             odr_seterror(o, OPROTO, 50);
43             return 0;
44         }
45         o->bp += res;
46         return 1;
47     case ODR_ENCODE:
48         if ((res = ber_encinteger(o, *val)) < 0)
49             return 0;
50         return 1;
51     case ODR_PRINT:
52         return 1;
53     default:
54         odr_seterror(o, OOTHER, 51);  return 0;
55     }
56 }
57
58 /*
59  * Returns: number of bytes written or -1 for error (out of bounds).
60  */
61 int ber_encinteger(ODR o, Odr_int val)
62 {
63     unsigned char tmp[sizeof(Odr_int)];
64     unsigned long long uval = val;
65     int i, len;
66     for (i = sizeof(uval); i > 0; )
67     {
68         tmp[--i] = uval;
69         uval >>= 8;
70     }
71     for (i = 0; i < sizeof(Odr_int)-1; i++)
72         if (!((tmp[i] == 0 && !(tmp[i+1] & 0x80))
73               ||
74               (tmp[i] == 0xFF && (tmp[i+1] & 0x80))))
75             break;
76     len = sizeof(Odr_int) - i;
77     if (ber_enclen(o, len, 1, 1) != 1)
78         return -1;
79     if (odr_write(o, (unsigned char*) tmp + i, len) < 0)
80         return -1;
81     return 0;
82 }
83
84 /*
85  * Returns: Number of bytes read or 0 if no match, -1 if error.
86  */
87 int ber_decinteger(const unsigned char *buf, Odr_int *val, int max)
88 {
89     unsigned long long uval = 0;
90     int i, len;
91     int res;
92     const unsigned char *b = buf;
93
94     if ((res = ber_declen(b, &len, max)) < 0)
95         return -1;
96     if (len+res > max || len < 0) /* out of bounds or indefinite encoding */
97         return -1;  
98     if (len > (int) sizeof(Odr_int))  /* let's be reasonable, here */
99         return -1;
100     b += res;
101
102     if (*b & 0x80)
103         for (i = 0; i < sizeof(uval) - len; i++)
104             uval = (uval << 8) + 0xFF;
105     for (i = 0; i < len; i++)
106         uval = (uval << 8) + b[i];
107     *val = uval;
108     b += len;
109     return b - buf;
110 }
111 /*
112  * Local variables:
113  * c-basic-offset: 4
114  * c-file-style: "Stroustrup"
115  * indent-tabs-mode: nil
116  * End:
117  * vim: shiftwidth=4 tabstop=8 expandtab
118  */
119