1 /*
2  * Integer functions
3  *
4  * Copyright (C) 2011-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 "pyevtx_error.h"
26 #include "pyevtx_libcerror.h"
27 #include "pyevtx_integer.h"
28 #include "pyevtx_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  */
pyevtx_integer_signed_new_from_64bit(int64_t value_64bit)33 PyObject *pyevtx_integer_signed_new_from_64bit(
34            int64_t value_64bit )
35 {
36 	PyObject *integer_object = NULL;
37 	static char *function    = "pyevtx_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  */
pyevtx_integer_unsigned_new_from_64bit(uint64_t value_64bit)71 PyObject *pyevtx_integer_unsigned_new_from_64bit(
72            uint64_t value_64bit )
73 {
74 	PyObject *integer_object = NULL;
75 	static char *function    = "pyevtx_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  */
pyevtx_integer_signed_copy_to_64bit(PyObject * integer_object,int64_t * value_64bit,libcerror_error_t ** error)108 int pyevtx_integer_signed_copy_to_64bit(
109      PyObject *integer_object,
110      int64_t *value_64bit,
111      libcerror_error_t **error )
112 {
113 	static char *function   = "pyevtx_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 		pyevtx_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 			pyevtx_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 		pyevtx_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  */
pyevtx_integer_unsigned_copy_to_64bit(PyObject * integer_object,uint64_t * value_64bit,libcerror_error_t ** error)249 int pyevtx_integer_unsigned_copy_to_64bit(
250      PyObject *integer_object,
251      uint64_t *value_64bit,
252      libcerror_error_t **error )
253 {
254 	static char *function   = "pyevtx_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 		pyevtx_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 			pyevtx_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 		pyevtx_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