1 /*
2  * Error functions
3  *
4  * Copyright (C) 2009-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 <memory.h>
24 #include <narrow_string.h>
25 #include <types.h>
26 
27 #if defined( HAVE_STDARG_H ) || defined( WINAPI )
28 #include <stdarg.h>
29 #elif defined( HAVE_VARARGS_H )
30 #include <varargs.h>
31 #else
32 #error Missing headers stdarg.h and varargs.h
33 #endif
34 
35 #include "pyesedb_error.h"
36 #include "pyesedb_libcerror.h"
37 #include "pyesedb_python.h"
38 
39 #if defined( HAVE_STDARG_H ) || defined( WINAPI )
40 #define VARARGS( function, error, error_domain, error_code, type, argument ) \
41 	function( error, error_domain, error_code, type argument, ... )
42 #define VASTART( argument_list, type, name ) \
43 	va_start( argument_list, name )
44 #define VAEND( argument_list ) \
45 	va_end( argument_list )
46 
47 #elif defined( HAVE_VARARGS_H )
48 #define VARARGS( function, error, error_domain, error_code, type, argument ) \
49 	function( error, error_domain, error_code, va_alist ) va_dcl
50 #define VASTART( argument_list, type, name ) \
51 	{ type name; va_start( argument_list ); name = va_arg( argument_list, type )
52 #define VAEND( argument_list ) \
53 	va_end( argument_list ); }
54 
55 #endif
56 
57 /* Fetches an error
58  */
VARARGS(pyesedb_error_fetch,libcerror_error_t ** error,int error_domain,int error_code,const char *,format_string)59 void VARARGS(
60       pyesedb_error_fetch,
61       libcerror_error_t **error,
62       int error_domain,
63       int error_code,
64       const char *,
65       format_string )
66 {
67 	va_list argument_list;
68 
69 	char error_string[ PYESEDB_ERROR_STRING_SIZE ];
70 
71         PyObject *exception_traceback = NULL;
72         PyObject *exception_type      = NULL;
73         PyObject *exception_value     = NULL;
74         PyObject *string_object       = NULL;
75 	static char *function         = "pyesedb_error_fetch";
76 	char *exception_string        = NULL;
77 	size_t error_string_length    = 0;
78 	int print_count               = 0;
79 
80 #if PY_MAJOR_VERSION >= 3
81 	PyObject *utf8_string_object  = NULL;
82 #endif
83 
84 	if( format_string == NULL )
85 	{
86 		PyErr_Format(
87 		 PyExc_ValueError,
88 		 "%s: missing format string.",
89 		 function );
90 
91 		return;
92 	}
93 	VASTART(
94 	 argument_list,
95 	 const char *,
96 	 format_string );
97 
98 	print_count = PyOS_vsnprintf(
99 	               error_string,
100 	               PYESEDB_ERROR_STRING_SIZE,
101 	               format_string,
102 	               argument_list );
103 
104 	VAEND(
105 	 argument_list );
106 
107 	if( print_count < 0 )
108 	{
109 		PyErr_Format(
110 		 PyExc_ValueError,
111 		 "%s: unable to format error string.",
112 		 function );
113 
114 		return;
115 	}
116 	error_string_length = narrow_string_length(
117 	                       error_string );
118 
119 	if( ( error_string_length >= 1 )
120 	 && ( error_string[ error_string_length - 1 ] == '.' ) )
121 	{
122 		error_string[ error_string_length - 1 ] = 0;
123 	}
124 	PyErr_Fetch(
125 	 &exception_type,
126 	 &exception_value,
127 	 &exception_traceback );
128 
129 	string_object = PyObject_Repr(
130 	                 exception_value );
131 
132 #if PY_MAJOR_VERSION >= 3
133 	utf8_string_object = PyUnicode_AsUTF8String(
134 	                      string_object );
135 
136 	if( utf8_string_object != NULL )
137 	{
138 		exception_string = PyBytes_AsString(
139 		                    utf8_string_object );
140 	}
141 #else
142 	exception_string = PyString_AsString(
143 	                    string_object );
144 #endif
145 	if( exception_string != NULL )
146 	{
147 		libcerror_error_set(
148 		 error,
149 		 error_domain,
150 		 error_code,
151 		 "%s with error: %s.",
152 		 error_string,
153 		 exception_string );
154 	}
155 	else
156 	{
157 		libcerror_error_set(
158 		 error,
159 		 error_domain,
160 		 error_code,
161 		 "%s.",
162 		 error_string );
163 	}
164 #if PY_MAJOR_VERSION >= 3
165 	if( utf8_string_object != NULL )
166 	{
167 		Py_DecRef(
168 		 utf8_string_object );
169 	}
170 #endif
171 	Py_DecRef(
172 	 string_object );
173 
174 	return;
175 }
176 
177 #undef VARARGS
178 #undef VASTART
179 #undef VAEND
180 
181 #if defined( HAVE_STDARG_H ) || defined( WINAPI )
182 #define VARARGS( function, exception_object, type, argument ) \
183 	function( exception_object, type argument, ... )
184 #define VASTART( argument_list, type, name ) \
185 	va_start( argument_list, name )
186 #define VAEND( argument_list ) \
187 	va_end( argument_list )
188 
189 #elif defined( HAVE_VARARGS_H )
190 #define VARARGS( function, exception_object, type, argument ) \
191 	function( exception_object, va_alist ) va_dcl
192 #define VASTART( argument_list, type, name ) \
193 	{ type name; va_start( argument_list ); name = va_arg( argument_list, type )
194 #define VAEND( argument_list ) \
195 	va_end( argument_list ); }
196 
197 #endif
198 
199 /* Fetches and raises an error
200  */
VARARGS(pyesedb_error_fetch_and_raise,PyObject * exception_object,const char *,format_string)201 void VARARGS(
202       pyesedb_error_fetch_and_raise,
203       PyObject *exception_object,
204       const char *,
205       format_string )
206 {
207 	va_list argument_list;
208 
209 	char error_string[ PYESEDB_ERROR_STRING_SIZE ];
210 
211 	PyObject *exception_traceback = NULL;
212 	PyObject *exception_type      = NULL;
213 	PyObject *exception_value     = NULL;
214 	PyObject *string_object       = NULL;
215 	static char *function         = "pyesedb_error_fetch_and_raise";
216 	char *exception_string        = NULL;
217 	size_t error_string_length    = 0;
218 	int print_count               = 0;
219 
220 #if PY_MAJOR_VERSION >= 3
221 	PyObject *utf8_string_object  = NULL;
222 #endif
223 
224 	if( format_string == NULL )
225 	{
226 		PyErr_Format(
227 		 PyExc_ValueError,
228 		 "%s: missing format string.",
229 		 function );
230 
231 		return;
232 	}
233 	VASTART(
234 	 argument_list,
235 	 const char *,
236 	 format_string );
237 
238 	print_count = PyOS_vsnprintf(
239 	               error_string,
240 	               PYESEDB_ERROR_STRING_SIZE,
241 	               format_string,
242 	               argument_list );
243 
244 	VAEND(
245 	 argument_list );
246 
247 	if( print_count < 0 )
248 	{
249 		PyErr_Format(
250 		 PyExc_ValueError,
251 		 "%s: unable to format exception string.",
252 		 function );
253 
254 		return;
255 	}
256 	error_string_length = narrow_string_length(
257 	                       error_string );
258 
259 	if( ( error_string_length >= 1 )
260 	 && ( error_string[ error_string_length - 1 ] == '.' ) )
261 	{
262 		error_string[ error_string_length - 1 ] = 0;
263 	}
264 	PyErr_Fetch(
265 	 &exception_type,
266 	 &exception_value,
267 	 &exception_traceback );
268 
269 	string_object = PyObject_Repr(
270 	                 exception_value );
271 
272 #if PY_MAJOR_VERSION >= 3
273 	utf8_string_object = PyUnicode_AsUTF8String(
274 	                      string_object );
275 
276 	if( utf8_string_object != NULL )
277 	{
278 		exception_string = PyBytes_AsString(
279 		                    utf8_string_object );
280 	}
281 #else
282 	exception_string = PyString_AsString(
283 	                    string_object );
284 #endif
285 	if( exception_string != NULL )
286 	{
287 		PyErr_Format(
288 		 exception_object,
289 		 "%s with error: %s.",
290 		 error_string,
291 		 exception_string );
292 	}
293 	else
294 	{
295 		PyErr_Format(
296 		 exception_object,
297 		 "%s.",
298 		 error_string );
299 	}
300 	Py_DecRef(
301 	 string_object );
302 
303 	return;
304 }
305 
306 #undef VARARGS
307 #undef VASTART
308 #undef VAEND
309 
310 #if defined( HAVE_STDARG_H ) || defined( WINAPI )
311 #define VARARGS( function, error, exception_object, type, argument ) \
312 	function( error, exception_object, type argument, ... )
313 #define VASTART( argument_list, type, name ) \
314 	va_start( argument_list, name )
315 #define VAEND( argument_list ) \
316 	va_end( argument_list )
317 
318 #elif defined( HAVE_VARARGS_H )
319 #define VARARGS( function, error, exception_object, type, argument ) \
320 	function( error, exception_object, va_alist ) va_dcl
321 #define VASTART( argument_list, type, name ) \
322 	{ type name; va_start( argument_list ); name = va_arg( argument_list, type )
323 #define VAEND( argument_list ) \
324 	va_end( argument_list ); }
325 
326 #endif
327 
328 /* Raises an error
329  */
VARARGS(pyesedb_error_raise,libcerror_error_t * error,PyObject * exception_object,const char *,format_string)330 void VARARGS(
331       pyesedb_error_raise,
332       libcerror_error_t *error,
333       PyObject *exception_object,
334       const char *,
335       format_string )
336 {
337 	va_list argument_list;
338 
339 	char error_string[ PYESEDB_ERROR_STRING_SIZE ];
340 	char exception_string[ PYESEDB_ERROR_STRING_SIZE ];
341 
342 	static char *function     = "pyesedb_error_raise";
343 	size_t error_string_index = 0;
344 	int print_count           = 0;
345 
346 	if( format_string == NULL )
347 	{
348 		PyErr_Format(
349 		 PyExc_ValueError,
350 		 "%s: missing format string.",
351 		 function );
352 
353 		return;
354 	}
355 	VASTART(
356 	 argument_list,
357 	 const char *,
358 	 format_string );
359 
360 	print_count = PyOS_vsnprintf(
361 	               exception_string,
362 	               PYESEDB_ERROR_STRING_SIZE,
363 	               format_string,
364 	               argument_list );
365 
366 	VAEND(
367 	 argument_list );
368 
369 	if( print_count < 0 )
370 	{
371 		PyErr_Format(
372 		 PyExc_ValueError,
373 		 "%s: unable to format exception string.",
374 		 function );
375 
376 		return;
377 	}
378 	if( error != NULL )
379 	{
380 		if( libcerror_error_backtrace_sprint(
381 		     error,
382 		     error_string,
383 		     PYESEDB_ERROR_STRING_SIZE ) != -1 )
384 		{
385 			while( error_string_index < PYESEDB_ERROR_STRING_SIZE )
386 			{
387 				if( error_string[ error_string_index ] == 0 )
388 				{
389 					break;
390 				}
391 				if( ( error_string[ error_string_index ] == '\n' )
392 				 || ( error_string[ error_string_index ] == '\r' ) )
393 				{
394 					error_string[ error_string_index ] = ' ';
395 				}
396 				error_string_index++;
397 			}
398 			if( error_string_index >= PYESEDB_ERROR_STRING_SIZE )
399 			{
400 				error_string[ PYESEDB_ERROR_STRING_SIZE - 1 ] = 0;
401 			}
402 			PyErr_Format(
403 			 exception_object,
404 			 "%s %s",
405 			 exception_string,
406 			 error_string );
407 
408 			return;
409 		}
410 	}
411 	PyErr_Format(
412 	 exception_object,
413 	 "%s",
414 	 exception_string );
415 
416 	return;
417 }
418 
419 #undef VARARGS
420 #undef VASTART
421 #undef VAEND
422 
423