xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_leb.c (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
1 /*
2   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
3   Portions Copyright 2011-2018 David Anderson. All Rights Reserved.
4 
5   This program is free software; you can redistribute it and/or modify it
6   under the terms of version 2.1 of the GNU Lesser General Public License
7   as published by the Free Software Foundation.
8 
9   This program is distributed in the hope that it would be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13   Further, this software is distributed without any warranty that it is
14   free of the rightful claim of any third person regarding infringement
15   or the like.  Any license provided herein, whether implied or
16   otherwise, applies only to this software file.  Patent licenses, if
17   any, provided herein do not apply to combinations of this program with
18   other software, or any other product whatsoever.
19 
20   You should have received a copy of the GNU Lesser General Public
21   License along with this program; if not, write the Free Software
22   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23   USA.
24 
25 */
26 
27 
28 #include "config.h"
29 #include <stdio.h>
30 #include "dwarf_incl.h"
31 #include "dwarf_error.h"
32 #include "dwarf_util.h"
33 
34 /*  Note that with 'make check')
35     many of the test items
36     only make sense if Dwarf_Unsigned (and Dwarf_Signed)
37     are 64 bits.  The encode/decode logic should
38     be fine whether those types are 64 or 32 bits.
39     See runtests.sh */
40 
41 /*  10 bytes of leb, 7 bits each part of the number, gives
42     room for a 64bit number.
43     While any number of leading zeroes would be legal, so
44     no max is really truly required here, why would a
45     compiler generate leading zeros?  That would
46     be strange.
47 */
48 #define BYTESLEBMAX 10
49 #define BITSPERBYTE 8
50 
51 
52 /* Decode ULEB with checking */
53 int
54 _dwarf_decode_u_leb128_chk(Dwarf_Small * leb128,
55     Dwarf_Unsigned * leb128_length,
56     Dwarf_Unsigned *outval,
57     Dwarf_Byte_Ptr endptr)
58 {
59     Dwarf_Unsigned byte     = 0;
60     Dwarf_Unsigned word_number = 0;
61     Dwarf_Unsigned number  = 0;
62     unsigned shift      = 0;
63     /*  The byte_length value will be a small non-negative integer. */
64     unsigned byte_length   = 0;
65 
66     if (leb128 >=endptr) {
67         return DW_DLV_ERROR;
68     }
69     /*  The following unrolls-the-loop for the first two bytes and
70         unpacks into 32 bits to make this as fast as possible.
71         word_number is assumed big enough that the shift has a defined
72         result. */
73     if ((*leb128 & 0x80) == 0) {
74         if (leb128_length) {
75             *leb128_length = 1;
76         }
77         *outval = *leb128;
78         return DW_DLV_OK;
79     } else {
80         if ((leb128+1) >=endptr) {
81             return DW_DLV_ERROR;
82         }
83         if ((*(leb128 + 1) & 0x80) == 0) {
84             if (leb128_length) {
85                 *leb128_length = 2;
86             }
87             word_number = *leb128 & 0x7f;
88             word_number |= (*(leb128 + 1) & 0x7f) << 7;
89             *outval = word_number;
90             return DW_DLV_OK;
91         }
92         /* Gets messy to hand-inline more byte checking. */
93     }
94 
95     /*  The rest handles long numbers Because the 'number' may be larger
96         than the default int/unsigned, we must cast the 'byte' before
97         the shift for the shift to have a defined result. */
98     number = 0;
99     shift = 0;
100     byte_length = 1;
101     byte = *leb128;
102     for (;;) {
103         if (shift >= (sizeof(number)*BITSPERBYTE)) {
104             return DW_DLV_ERROR;
105         }
106         number |= (byte & 0x7f) << shift;
107         if ((byte & 0x80) == 0) {
108             if (leb128_length) {
109                 *leb128_length = byte_length;
110             }
111             *outval = number;
112             return DW_DLV_OK;
113         }
114         shift += 7;
115         byte_length++;
116         if (byte_length > BYTESLEBMAX) {
117             /*  Erroneous input.  */
118             if( leb128_length) {
119                 *leb128_length = BYTESLEBMAX;
120             }
121             break;
122         }
123         ++leb128;
124         if ((leb128) >=endptr) {
125             return DW_DLV_ERROR;
126         }
127         byte = *leb128;
128     }
129     return DW_DLV_ERROR;
130 }
131 
132 
133 #define BITSINBYTE 8
134 
135 int
136 _dwarf_decode_s_leb128_chk(Dwarf_Small * leb128, Dwarf_Unsigned * leb128_length,
137     Dwarf_Signed *outval,Dwarf_Byte_Ptr endptr)
138 {
139     Dwarf_Unsigned byte   = 0;
140     Dwarf_Signed number  = 0;
141     Dwarf_Bool sign      = 0;
142     Dwarf_Unsigned shift     = 0;
143     /*  The byte_length value will be a small non-negative integer. */
144     unsigned byte_length = 1;
145 
146     /*  byte_length being the number of bytes of data absorbed so far in
147         turning the leb into a Dwarf_Signed. */
148     if (!outval) {
149         return DW_DLV_ERROR;
150     }
151     if (leb128 >= endptr) {
152         return DW_DLV_ERROR;
153     }
154     byte   = *leb128;
155     for (;;) {
156         sign = byte & 0x40;
157         if (shift >= (sizeof(number)*BITSPERBYTE)) {
158             return DW_DLV_ERROR;
159         }
160         number |= ((Dwarf_Unsigned) ((byte & 0x7f))) << shift;
161         shift += 7;
162 
163         if ((byte & 0x80) == 0) {
164             break;
165         }
166         ++leb128;
167         if (leb128 >= endptr) {
168             return DW_DLV_ERROR;
169         }
170         byte = *leb128;
171         byte_length++;
172         if (byte_length > BYTESLEBMAX) {
173             /*  Erroneous input. */
174             if (leb128_length) {
175                 *leb128_length = BYTESLEBMAX;
176             }
177             return DW_DLV_ERROR;
178         }
179     }
180 
181     if (sign) {
182         /* The following avoids undefined behavior. */
183         unsigned shiftlim = sizeof(Dwarf_Signed) * BITSINBYTE -1;
184         if (shift < shiftlim) {
185             number |= -(Dwarf_Signed)(((Dwarf_Unsigned)1) << shift);
186         } else if (shift == shiftlim) {
187             number |= (((Dwarf_Unsigned)1) << shift);
188         }
189     }
190 
191     if (leb128_length) {
192         *leb128_length = byte_length;
193     }
194     *outval = number;
195     return DW_DLV_OK;
196 }
197