1 /*
2 * Integer functions
3 *
4 * Copyright (C) 2013-2021, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <types.h>
24
25 #include "pycreg_error.h"
26 #include "pycreg_libcerror.h"
27 #include "pycreg_integer.h"
28 #include "pycreg_python.h"
29
30 /* Creates a new signed integer object from a 64-bit value
31 * Returns a Python object if successful or NULL on error
32 */
pycreg_integer_signed_new_from_64bit(int64_t value_64bit)33 PyObject *pycreg_integer_signed_new_from_64bit(
34 int64_t value_64bit )
35 {
36 PyObject *integer_object = NULL;
37 static char *function = "pycreg_integer_signed_new_from_64bit";
38
39 #if defined( HAVE_LONG_LONG )
40 if( ( value_64bit < (int64_t) LLONG_MIN )
41 || ( value_64bit > (int64_t) LLONG_MAX ) )
42 {
43 PyErr_Format(
44 PyExc_OverflowError,
45 "%s: 64-bit value out of bounds.",
46 function );
47
48 return( NULL );
49 }
50 integer_object = PyLong_FromLongLong(
51 (long long) value_64bit );
52 #else
53 if( current_offset > (off64_t) LONG_MAX )
54 {
55 PyErr_Format(
56 PyExc_OverflowError,
57 "%s: 64-bit value out of bounds.",
58 function );
59
60 return( NULL );
61 }
62 integer_object = PyLong_FromLong(
63 (long) value_64bit );
64 #endif
65 return( integer_object );
66 }
67
68 /* Creates a new unsigned integer object from a 64-bit value
69 * Returns a Python object if successful or NULL on error
70 */
pycreg_integer_unsigned_new_from_64bit(uint64_t value_64bit)71 PyObject *pycreg_integer_unsigned_new_from_64bit(
72 uint64_t value_64bit )
73 {
74 PyObject *integer_object = NULL;
75 static char *function = "pycreg_integer_unsigned_new_from_64bit";
76
77 #if defined( HAVE_LONG_LONG )
78 if( value_64bit > (uint64_t) ULLONG_MAX )
79 {
80 PyErr_Format(
81 PyExc_OverflowError,
82 "%s: 64-bit value exceeds maximum.",
83 function );
84
85 return( NULL );
86 }
87 integer_object = PyLong_FromUnsignedLongLong(
88 (long long) value_64bit );
89 #else
90 if( value_64bit > (uint64_t) ULONG_MAX )
91 {
92 PyErr_Format(
93 PyExc_OverflowError,
94 "%s: 64-bit value exceeds maximum.",
95 function );
96
97 return( NULL );
98 }
99 integer_object = PyLong_FromUnsignedLong(
100 (long) value_64bit );
101 #endif
102 return( integer_object );
103 }
104
105 /* Copies a Python int or long object to a signed 64-bit value
106 * Returns 1 if successful or -1 on error
107 */
pycreg_integer_signed_copy_to_64bit(PyObject * integer_object,int64_t * value_64bit,libcerror_error_t ** error)108 int pycreg_integer_signed_copy_to_64bit(
109 PyObject *integer_object,
110 int64_t *value_64bit,
111 libcerror_error_t **error )
112 {
113 static char *function = "pycreg_integer_signed_copy_to_64bit";
114 int result = 0;
115
116 #if defined( HAVE_LONG_LONG )
117 PY_LONG_LONG long_value = 0;
118 #else
119 long long_value = 0;
120 #endif
121
122 if( integer_object == NULL )
123 {
124 libcerror_error_set(
125 error,
126 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
127 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
128 "%s: invalid integer object.",
129 function );
130
131 return( -1 );
132 }
133 PyErr_Clear();
134
135 result = PyObject_IsInstance(
136 integer_object,
137 (PyObject *) &PyLong_Type );
138
139 if( result == -1 )
140 {
141 pycreg_error_fetch(
142 error,
143 LIBCERROR_ERROR_DOMAIN_RUNTIME,
144 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
145 "%s: unable to determine if integer object is of type long.",
146 function );
147
148 return( -1 );
149 }
150 else if( result != 0 )
151 {
152 PyErr_Clear();
153
154 #if defined( HAVE_LONG_LONG )
155 long_value = PyLong_AsLongLong(
156 integer_object );
157 #else
158 long_value = PyLong_AsLong(
159 integer_object );
160 #endif
161 }
162 #if PY_MAJOR_VERSION < 3
163 if( result == 0 )
164 {
165 PyErr_Clear();
166
167 result = PyObject_IsInstance(
168 integer_object,
169 (PyObject *) &PyInt_Type );
170
171 if( result == -1 )
172 {
173 pycreg_error_fetch(
174 error,
175 LIBCERROR_ERROR_DOMAIN_RUNTIME,
176 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
177 "%s: unable to determine if integer object is of type int.",
178 function );
179
180 return( -1 );
181 }
182 else if( result != 0 )
183 {
184 PyErr_Clear();
185
186 long_value = PyInt_AsLong(
187 integer_object );
188 }
189 }
190 #endif /* PY_MAJOR_VERSION < 3 */
191
192 if( result == 0 )
193 {
194 libcerror_error_set(
195 error,
196 LIBCERROR_ERROR_DOMAIN_RUNTIME,
197 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
198 "%s: unsupported integer object type.",
199 function );
200
201 return( -1 );
202 }
203 if( PyErr_Occurred() )
204 {
205 pycreg_error_fetch(
206 error,
207 LIBCERROR_ERROR_DOMAIN_RUNTIME,
208 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
209 "%s: unable to convert integer object to long.",
210 function );
211
212 return( -1 );
213 }
214 #if defined( HAVE_LONG_LONG ) && ( SIZEOF_LONG_LONG > 8 )
215 if( ( long_value < (PY_LONG_LONG) INT64_MIN )
216 || ( long_value > (PY_LONG_LONG) INT64_MAX ) )
217 {
218 libcerror_error_set(
219 error,
220 LIBCERROR_ERROR_DOMAIN_RUNTIME,
221 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
222 "%s: invalid long value out of bounds.",
223 function );
224
225 return( -1 );
226 }
227 #elif ( SIZEOF_LONG > 8 )
228 if( ( long_value > (long) INT64_MIN )
229 || ( long_value > (long) INT64_MAX ) )
230 {
231 libcerror_error_set(
232 error,
233 LIBCERROR_ERROR_DOMAIN_RUNTIME,
234 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
235 "%s: invalid long value out of bounds.",
236 function );
237
238 return( -1 );
239 }
240 #endif
241 *value_64bit = (int64_t) long_value;
242
243 return( 1 );
244 }
245
246 /* Copies a Python int or long object to an unsigned 64-bit value
247 * Returns 1 if successful or -1 on error
248 */
pycreg_integer_unsigned_copy_to_64bit(PyObject * integer_object,uint64_t * value_64bit,libcerror_error_t ** error)249 int pycreg_integer_unsigned_copy_to_64bit(
250 PyObject *integer_object,
251 uint64_t *value_64bit,
252 libcerror_error_t **error )
253 {
254 static char *function = "pycreg_integer_unsigned_copy_to_64bit";
255 int result = 0;
256
257 #if defined( HAVE_LONG_LONG )
258 PY_LONG_LONG long_value = 0;
259 #else
260 long long_value = 0;
261 #endif
262
263 if( integer_object == NULL )
264 {
265 libcerror_error_set(
266 error,
267 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
268 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
269 "%s: invalid integer object.",
270 function );
271
272 return( -1 );
273 }
274 PyErr_Clear();
275
276 result = PyObject_IsInstance(
277 integer_object,
278 (PyObject *) &PyLong_Type );
279
280 if( result == -1 )
281 {
282 pycreg_error_fetch(
283 error,
284 LIBCERROR_ERROR_DOMAIN_RUNTIME,
285 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
286 "%s: unable to determine if integer object is of type long.",
287 function );
288
289 return( -1 );
290 }
291 else if( result != 0 )
292 {
293 PyErr_Clear();
294
295 #if defined( HAVE_LONG_LONG )
296 long_value = PyLong_AsUnsignedLongLong(
297 integer_object );
298 #else
299 long_value = PyLong_AsUnsignedLong(
300 integer_object );
301 #endif
302 }
303 #if PY_MAJOR_VERSION < 3
304 if( result == 0 )
305 {
306 PyErr_Clear();
307
308 result = PyObject_IsInstance(
309 integer_object,
310 (PyObject *) &PyInt_Type );
311
312 if( result == -1 )
313 {
314 pycreg_error_fetch(
315 error,
316 LIBCERROR_ERROR_DOMAIN_RUNTIME,
317 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
318 "%s: unable to determine if integer object is of type int.",
319 function );
320
321 return( -1 );
322 }
323 else if( result != 0 )
324 {
325 PyErr_Clear();
326
327 #if defined( HAVE_LONG_LONG )
328 long_value = PyInt_AsUnsignedLongLongMask(
329 integer_object );
330 #else
331 long_value = PyInt_AsUnsignedLongMask(
332 integer_object );
333 #endif
334 }
335 }
336 #endif /* PY_MAJOR_VERSION < 3 */
337
338 if( result == 0 )
339 {
340 libcerror_error_set(
341 error,
342 LIBCERROR_ERROR_DOMAIN_RUNTIME,
343 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
344 "%s: unsupported integer object type.",
345 function );
346
347 return( -1 );
348 }
349 if( PyErr_Occurred() )
350 {
351 pycreg_error_fetch(
352 error,
353 LIBCERROR_ERROR_DOMAIN_RUNTIME,
354 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
355 "%s: unable to convert integer object to long.",
356 function );
357
358 return( -1 );
359 }
360 #if defined( HAVE_LONG_LONG )
361 #if ( SIZEOF_LONG_LONG > 8 )
362 if( ( long_value < (PY_LONG_LONG) 0 )
363 || ( long_value > (PY_LONG_LONG) UINT64_MAX ) )
364 #else
365 if( long_value < (PY_LONG_LONG) 0 )
366 #endif
367 {
368 libcerror_error_set(
369 error,
370 LIBCERROR_ERROR_DOMAIN_RUNTIME,
371 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
372 "%s: invalid long value out of bounds.",
373 function );
374
375 return( -1 );
376 }
377 #else
378 #if ( SIZEOF_LONG > 8 )
379 if( ( long_value < (long) 0 )
380 || ( long_value > (long) UINT64_MAX ) )
381 #else
382 if( long_value < (PY_LONG_LONG) 0 )
383 #endif
384 {
385 libcerror_error_set(
386 error,
387 LIBCERROR_ERROR_DOMAIN_RUNTIME,
388 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
389 "%s: invalid long value out of bounds.",
390 function );
391
392 return( -1 );
393 }
394 #endif
395 *value_64bit = (uint64_t) long_value;
396
397 return( 1 );
398 }
399
400