1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % EEEEE X X CCCC EEEEE PPPP TTTTT IIIII OOO N N %
7 % E X X C E P P T I O O NN N %
8 % EEE X C EEE PPPP T I O O N N N %
9 % E X X C E P T I O O N NN %
10 % EEEEE X X CCCC EEEEE P T IIIII OOO N N %
11 % %
12 % %
13 % MagickCore Exception Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1993 %
18 % %
19 % %
20 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 %
38 */
39
40 /*
41 Include declarations.
42 */
43 #include "magick/studio.h"
44 #include "magick/client.h"
45 #include "magick/exception.h"
46 #include "magick/exception-private.h"
47 #include "magick/hashmap.h"
48 #include "magick/locale_.h"
49 #include "magick/log.h"
50 #include "magick/magick.h"
51 #include "magick/memory_.h"
52 #include "magick/semaphore.h"
53 #include "magick/string_.h"
54 #include "magick/utility.h"
55
56 /*
57 Define declarations.
58 */
59 #define MaxExceptionList 64
60
61 /*
62 Forward declarations.
63 */
64 #if defined(__cplusplus) || defined(c_plusplus)
65 extern "C" {
66 #endif
67
68 static void
69 DefaultErrorHandler(const ExceptionType,const char *,const char *),
70 DefaultFatalErrorHandler(const ExceptionType,const char *,const char *),
71 DefaultWarningHandler(const ExceptionType,const char *,const char *);
72
73 #if defined(__cplusplus) || defined(c_plusplus)
74 }
75 #endif
76
77 /*
78 Global declarations.
79 */
80 static ErrorHandler
81 error_handler = DefaultErrorHandler;
82
83 static FatalErrorHandler
84 fatal_error_handler = DefaultFatalErrorHandler;
85
86 static WarningHandler
87 warning_handler = DefaultWarningHandler;
88
89 /*
90 Static declarations.
91 */
92 static SemaphoreInfo
93 *exception_semaphore = (SemaphoreInfo *) NULL;
94
95 /*
96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97 % %
98 % %
99 % %
100 % A c q u i r e E x c e p t i o n I n f o %
101 % %
102 % %
103 % %
104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105 %
106 % AcquireExceptionInfo() allocates the ExceptionInfo structure.
107 %
108 % The format of the AcquireExceptionInfo method is:
109 %
110 % ExceptionInfo *AcquireExceptionInfo(void)
111 %
112 */
AcquireExceptionInfo(void)113 MagickExport ExceptionInfo *AcquireExceptionInfo(void)
114 {
115 ExceptionInfo
116 *exception;
117
118 exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
119 if (exception == (ExceptionInfo *) NULL)
120 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
121 InitializeExceptionInfo(exception);
122 exception->relinquish=MagickTrue;
123 return(exception);
124 }
125
126 /*
127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128 % %
129 % %
130 % %
131 % C l e a r M a g i c k E x c e p t i o n %
132 % %
133 % %
134 % %
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 %
137 % ClearMagickException() clears any exception that may not have been caught
138 % yet.
139 %
140 % The format of the ClearMagickException method is:
141 %
142 % ClearMagickException(ExceptionInfo *exception)
143 %
144 % A description of each parameter follows:
145 %
146 % o exception: the exception info.
147 %
148 */
149
DestroyExceptionElement(void * exception)150 static void *DestroyExceptionElement(void *exception)
151 {
152 ExceptionInfo
153 *p;
154
155 p=(ExceptionInfo *) exception;
156 if (p->reason != (char *) NULL)
157 p->reason=DestroyString(p->reason);
158 if (p->description != (char *) NULL)
159 p->description=DestroyString(p->description);
160 p=(ExceptionInfo *) RelinquishMagickMemory(p);
161 return((void *) NULL);
162 }
163
ClearMagickException(ExceptionInfo * exception)164 MagickExport void ClearMagickException(ExceptionInfo *exception)
165 {
166 assert(exception != (ExceptionInfo *) NULL);
167 assert(exception->signature == MagickCoreSignature);
168 if (exception->exceptions == (void *) NULL)
169 return;
170 LockSemaphoreInfo(exception->semaphore);
171 ClearLinkedList((LinkedListInfo *) exception->exceptions,
172 DestroyExceptionElement);
173 exception->severity=UndefinedException;
174 exception->reason=(char *) NULL;
175 exception->description=(char *) NULL;
176 UnlockSemaphoreInfo(exception->semaphore);
177 errno=0;
178 }
179
180 /*
181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
182 % %
183 % %
184 % %
185 % C a t c h E x c e p t i o n %
186 % %
187 % %
188 % %
189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190 %
191 % CatchException() returns if no exceptions is found otherwise it reports
192 % the exception as a warning, error, or fatal depending on the severity.
193 %
194 % The format of the CatchException method is:
195 %
196 % CatchException(ExceptionInfo *exception)
197 %
198 % A description of each parameter follows:
199 %
200 % o exception: the exception info.
201 %
202 */
CatchException(ExceptionInfo * exception)203 MagickExport void CatchException(ExceptionInfo *exception)
204 {
205 LinkedListInfo
206 *exceptions;
207
208 const ExceptionInfo
209 *p;
210
211 ssize_t
212 i;
213
214 assert(exception != (ExceptionInfo *) NULL);
215 assert(exception->signature == MagickCoreSignature);
216 if (exception->exceptions == (void *) NULL)
217 return;
218 LockSemaphoreInfo(exception->semaphore);
219 exceptions=(LinkedListInfo *) exception->exceptions;
220 ResetLinkedListIterator(exceptions);
221 p=(const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
222 for (i=0; p != (const ExceptionInfo *) NULL; i++)
223 {
224 if (p->severity >= FatalErrorException)
225 MagickFatalError(p->severity,p->reason,p->description);
226 if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
227 MagickError(p->severity,p->reason,p->description);
228 if ((p->severity >= WarningException) && (p->severity < ErrorException))
229 MagickWarning(p->severity,p->reason,p->description);
230 p=(const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
231 }
232 UnlockSemaphoreInfo(exception->semaphore);
233 ClearMagickException(exception);
234 }
235
236 /*
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 % %
239 % %
240 % %
241 % C l o n e E x c e p t i o n I n f o %
242 % %
243 % %
244 % %
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 %
247 % CloneExceptionInfo() clones the ExceptionInfo structure.
248 %
249 % The format of the CloneExceptionInfo method is:
250 %
251 % ExceptionInfo *CloneException(ExceptionInfo *exception)
252 %
253 % A description of each parameter follows:
254 %
255 % o exception: the exception info.
256 %
257 */
CloneExceptionInfo(ExceptionInfo * exception)258 MagickExport ExceptionInfo *CloneExceptionInfo(ExceptionInfo *exception)
259 {
260 ExceptionInfo
261 *clone_exception;
262
263 clone_exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception));
264 if (clone_exception == (ExceptionInfo *) NULL)
265 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
266 InitializeExceptionInfo(clone_exception);
267 InheritException(clone_exception,exception);
268 clone_exception->relinquish=MagickTrue;
269 return(clone_exception);
270 }
271
272 /*
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 % %
275 % %
276 % %
277 + D e f a u l t E r r o r H a n d l e r %
278 % %
279 % %
280 % %
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 %
283 % DefaultErrorHandler() displays an error reason.
284 %
285 % The format of the DefaultErrorHandler method is:
286 %
287 % void MagickError(const ExceptionType severity,const char *reason,
288 % const char *description)
289 %
290 % A description of each parameter follows:
291 %
292 % o severity: Specifies the numeric error category.
293 %
294 % o reason: Specifies the reason to display before terminating the
295 % program.
296 %
297 % o description: Specifies any description to the reason.
298 %
299 */
DefaultErrorHandler(const ExceptionType magick_unused (severity),const char * reason,const char * description)300 static void DefaultErrorHandler(const ExceptionType magick_unused(severity),
301 const char *reason,const char *description)
302 {
303 magick_unreferenced(severity);
304
305 if (reason == (char *) NULL)
306 return;
307 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
308 if (description != (char *) NULL)
309 (void) FormatLocaleFile(stderr," (%s)",description);
310 (void) FormatLocaleFile(stderr,".\n");
311 (void) fflush(stderr);
312 }
313
314 /*
315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316 % %
317 % %
318 % %
319 + D e f a u l t F a t a l E r r o r H a n d l e r %
320 % %
321 % %
322 % %
323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324 %
325 % DefaultFatalErrorHandler() displays an error reason and then terminates the
326 % program.
327 %
328 % The format of the DefaultFatalErrorHandler method is:
329 %
330 % void MagickFatalError(const ExceptionType severity,const char *reason,
331 % const char *description)
332 %
333 % A description of each parameter follows:
334 %
335 % o severity: Specifies the numeric error category.
336 %
337 % o reason: Specifies the reason to display before terminating the program.
338 %
339 % o description: Specifies any description to the reason.
340 %
341 */
DefaultFatalErrorHandler(const ExceptionType severity,const char * reason,const char * description)342 static void DefaultFatalErrorHandler(const ExceptionType severity,
343 const char *reason,const char *description)
344 {
345 if (reason == (char *) NULL)
346 return;
347 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
348 if (description != (char *) NULL)
349 (void) FormatLocaleFile(stderr," (%s)",description);
350 (void) FormatLocaleFile(stderr,".\n");
351 (void) fflush(stderr);
352 MagickCoreTerminus();
353 exit((int) (severity-FatalErrorException)+1);
354 }
355
356 /*
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
358 % %
359 % %
360 % %
361 + D e f a u l t W a r n i n g H a n d l e r %
362 % %
363 % %
364 % %
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 %
367 % DefaultWarningHandler() displays a warning reason.
368 %
369 % The format of the DefaultWarningHandler method is:
370 %
371 % void DefaultWarningHandler(const ExceptionType severity,
372 % const char *reason,const char *description)
373 %
374 % A description of each parameter follows:
375 %
376 % o severity: Specifies the numeric warning category.
377 %
378 % o reason: Specifies the reason to display before terminating the
379 % program.
380 %
381 % o description: Specifies any description to the reason.
382 %
383 */
DefaultWarningHandler(const ExceptionType magick_unused (severity),const char * reason,const char * description)384 static void DefaultWarningHandler(const ExceptionType magick_unused(severity),
385 const char *reason,const char *description)
386 {
387 magick_unreferenced(severity);
388
389 if (reason == (char *) NULL)
390 return;
391 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason);
392 if (description != (char *) NULL)
393 (void) FormatLocaleFile(stderr," (%s)",description);
394 (void) FormatLocaleFile(stderr,".\n");
395 (void) fflush(stderr);
396 }
397
398 /*
399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 % %
401 % %
402 % %
403 % D e s t r o y E x c e p t i o n I n f o %
404 % %
405 % %
406 % %
407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
408 %
409 % DestroyExceptionInfo() deallocates memory associated with an exception.
410 %
411 % The format of the DestroyExceptionInfo method is:
412 %
413 % ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
414 %
415 % A description of each parameter follows:
416 %
417 % o exception: the exception info.
418 %
419 */
420
ClearExceptionInfo(ExceptionInfo * exception,MagickBooleanType relinquish)421 MagickPrivate MagickBooleanType ClearExceptionInfo(ExceptionInfo *exception,
422 MagickBooleanType relinquish)
423 {
424 assert(exception != (ExceptionInfo *) NULL);
425 assert(exception->signature == MagickCoreSignature);
426 if (exception->semaphore == (SemaphoreInfo *) NULL)
427 ActivateSemaphoreInfo(&exception->semaphore);
428 LockSemaphoreInfo(exception->semaphore);
429 if (relinquish == MagickFalse)
430 relinquish=exception->relinquish;
431 exception->severity=UndefinedException;
432 if (relinquish != MagickFalse)
433 {
434 exception->signature=(~MagickCoreSignature);
435 if (exception->exceptions != (void *) NULL)
436 exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *)
437 exception->exceptions,DestroyExceptionElement);
438 }
439 else if (exception->exceptions != (void *) NULL)
440 ClearLinkedList((LinkedListInfo *) exception->exceptions,
441 DestroyExceptionElement);
442 UnlockSemaphoreInfo(exception->semaphore);
443 if (relinquish != MagickFalse)
444 DestroySemaphoreInfo(&exception->semaphore);
445 return(relinquish);
446 }
447
DestroyExceptionInfo(ExceptionInfo * exception)448 MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
449 {
450 if (ClearExceptionInfo(exception,MagickFalse) != MagickFalse)
451 exception=(ExceptionInfo *) RelinquishMagickMemory(exception);
452 return(exception);
453 }
454
455 /*
456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 % %
458 % %
459 % %
460 + E x e c e p t i o n C o m p o n e n t G e n e s i s %
461 % %
462 % %
463 % %
464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465 %
466 % ExceptionComponentGenesis() instantiates the exception component.
467 %
468 % The format of the ExceptionComponentGenesis method is:
469 %
470 % MagickBooleanType ExceptionComponentGenesis(void)
471 %
472 */
ExceptionComponentGenesis(void)473 MagickPrivate MagickBooleanType ExceptionComponentGenesis(void)
474 {
475 if (exception_semaphore == (SemaphoreInfo *) NULL)
476 exception_semaphore=AllocateSemaphoreInfo();
477 return(MagickTrue);
478 }
479
480 /*
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482 % %
483 % %
484 % %
485 + E x c e p t i o n C o m p o n e n t T e r m i n u s %
486 % %
487 % %
488 % %
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490 %
491 % ExceptionComponentTerminus() destroys the exception component.
492 %
493 % The format of the ExceptionComponentTerminus method is:
494 %
495 % void ExceptionComponentTerminus(void)
496 %
497 */
ExceptionComponentTerminus(void)498 MagickPrivate void ExceptionComponentTerminus(void)
499 {
500 if (exception_semaphore == (SemaphoreInfo *) NULL)
501 ActivateSemaphoreInfo(&exception_semaphore);
502 LockSemaphoreInfo(exception_semaphore);
503 UnlockSemaphoreInfo(exception_semaphore);
504 DestroySemaphoreInfo(&exception_semaphore);
505 }
506
507 /*
508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
509 % %
510 % %
511 % %
512 % G e t E x c e p t i o n M e s s a g e %
513 % %
514 % %
515 % %
516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
517 %
518 % GetExceptionMessage() returns the error message defined by the specified
519 % error code.
520 %
521 % The format of the GetExceptionMessage method is:
522 %
523 % char *GetExceptionMessage(const int error)
524 %
525 % A description of each parameter follows:
526 %
527 % o error: the error code.
528 %
529 */
GetExceptionMessage(const int error)530 MagickExport char *GetExceptionMessage(const int error)
531 {
532 char
533 exception[MaxTextExtent];
534
535 *exception='\0';
536 #if defined(MAGICKCORE_HAVE_STRERROR_R)
537 #if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
538 (void) strerror_r(error,exception,sizeof(exception));
539 #else
540 (void) CopyMagickString(exception,strerror_r(error,exception,
541 sizeof(exception)),sizeof(exception));
542 #endif
543 #else
544 (void) CopyMagickString(exception,strerror(error),sizeof(exception));
545 #endif
546 return(ConstantString(exception));
547 }
548
549 /*
550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551 % %
552 % %
553 % %
554 % G e t L o c a l e E x c e p t i o n M e s s a g e %
555 % %
556 % %
557 % %
558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559 %
560 % GetLocaleExceptionMessage() converts a enumerated exception severity and tag
561 % to a message in the current locale.
562 %
563 % The format of the GetLocaleExceptionMessage method is:
564 %
565 % const char *GetLocaleExceptionMessage(const ExceptionType severity,
566 % const char *tag)
567 %
568 % A description of each parameter follows:
569 %
570 % o severity: the severity of the exception.
571 %
572 % o tag: the message tag.
573 %
574 */
575
ExceptionSeverityToTag(const ExceptionType severity)576 static const char *ExceptionSeverityToTag(const ExceptionType severity)
577 {
578 switch (severity)
579 {
580 case ResourceLimitWarning: return("Resource/Limit/Warning/");
581 case TypeWarning: return("Type/Warning/");
582 case OptionWarning: return("Option/Warning/");
583 case DelegateWarning: return("Delegate/Warning/");
584 case MissingDelegateWarning: return("Missing/Delegate/Warning/");
585 case CorruptImageWarning: return("Corrupt/Image/Warning/");
586 case FileOpenWarning: return("File/Open/Warning/");
587 case BlobWarning: return("Blob/Warning/");
588 case StreamWarning: return("Stream/Warning/");
589 case CacheWarning: return("Cache/Warning/");
590 case CoderWarning: return("Coder/Warning/");
591 case FilterWarning: return("Filter/Warning/");
592 case ModuleWarning: return("Module/Warning/");
593 case DrawWarning: return("Draw/Warning/");
594 case ImageWarning: return("Image/Warning/");
595 case WandWarning: return("Wand/Warning/");
596 case XServerWarning: return("XServer/Warning/");
597 case MonitorWarning: return("Monitor/Warning/");
598 case RegistryWarning: return("Registry/Warning/");
599 case ConfigureWarning: return("Configure/Warning/");
600 case PolicyWarning: return("Policy/Warning/");
601 case ResourceLimitError: return("Resource/Limit/Error/");
602 case TypeError: return("Type/Error/");
603 case OptionError: return("Option/Error/");
604 case DelegateError: return("Delegate/Error/");
605 case MissingDelegateError: return("Missing/Delegate/Error/");
606 case CorruptImageError: return("Corrupt/Image/Error/");
607 case FileOpenError: return("File/Open/Error/");
608 case BlobError: return("Blob/Error/");
609 case StreamError: return("Stream/Error/");
610 case CacheError: return("Cache/Error/");
611 case CoderError: return("Coder/Error/");
612 case FilterError: return("Filter/Error/");
613 case ModuleError: return("Module/Error/");
614 case DrawError: return("Draw/Error/");
615 case ImageError: return("Image/Error/");
616 case WandError: return("Wand/Error/");
617 case XServerError: return("XServer/Error/");
618 case MonitorError: return("Monitor/Error/");
619 case RegistryError: return("Registry/Error/");
620 case ConfigureError: return("Configure/Error/");
621 case PolicyError: return("Policy/Error/");
622 case ResourceLimitFatalError: return("Resource/Limit/FatalError/");
623 case TypeFatalError: return("Type/FatalError/");
624 case OptionFatalError: return("Option/FatalError/");
625 case DelegateFatalError: return("Delegate/FatalError/");
626 case MissingDelegateFatalError: return("Missing/Delegate/FatalError/");
627 case CorruptImageFatalError: return("Corrupt/Image/FatalError/");
628 case FileOpenFatalError: return("File/Open/FatalError/");
629 case BlobFatalError: return("Blob/FatalError/");
630 case StreamFatalError: return("Stream/FatalError/");
631 case CacheFatalError: return("Cache/FatalError/");
632 case CoderFatalError: return("Coder/FatalError/");
633 case FilterFatalError: return("Filter/FatalError/");
634 case ModuleFatalError: return("Module/FatalError/");
635 case DrawFatalError: return("Draw/FatalError/");
636 case ImageFatalError: return("Image/FatalError/");
637 case WandFatalError: return("Wand/FatalError/");
638 case XServerFatalError: return("XServer/FatalError/");
639 case MonitorFatalError: return("Monitor/FatalError/");
640 case RegistryFatalError: return("Registry/FatalError/");
641 case ConfigureFatalError: return("Configure/FatalError/");
642 case PolicyFatalError: return("Policy/FatalError/");
643 default: break;
644 }
645 return("");
646 }
647
GetLocaleExceptionMessage(const ExceptionType severity,const char * tag)648 MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity,
649 const char *tag)
650 {
651 char
652 message[MaxTextExtent];
653
654 const char
655 *locale_message;
656
657 assert(tag != (const char *) NULL);
658 (void) FormatLocaleString(message,MaxTextExtent,"Exception/%s%s",
659 ExceptionSeverityToTag(severity),tag);
660 locale_message=GetLocaleMessage(message);
661 if (locale_message == (const char *) NULL)
662 return(tag);
663 if (locale_message == message)
664 return(tag);
665 return(locale_message);
666 }
667
668 /*
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 % %
671 % %
672 % %
673 % I n h e r i t E x c e p t i o n %
674 % %
675 % %
676 % %
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 %
679 % InheritException() inherits an exception from a related exception.
680 %
681 % The format of the InheritException method is:
682 %
683 % InheritException(ExceptionInfo *exception,const ExceptionInfo *relative)
684 %
685 % A description of each parameter follows:
686 %
687 % o exception: the exception info.
688 %
689 % o relative: the related exception info.
690 %
691 */
InheritException(ExceptionInfo * exception,const ExceptionInfo * relative)692 MagickExport void InheritException(ExceptionInfo *exception,
693 const ExceptionInfo *relative)
694 {
695 const ExceptionInfo
696 *p;
697
698 assert(exception != (ExceptionInfo *) NULL);
699 assert(exception->signature == MagickCoreSignature);
700 assert(relative != (ExceptionInfo *) NULL);
701 assert(relative->signature == MagickCoreSignature);
702 assert(exception != relative);
703 if (relative->exceptions == (void *) NULL)
704 return;
705 LockSemaphoreInfo(relative->semaphore);
706 ResetLinkedListIterator((LinkedListInfo *) relative->exceptions);
707 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
708 relative->exceptions);
709 while (p != (const ExceptionInfo *) NULL)
710 {
711 (void) ThrowException(exception,p->severity,p->reason,p->description);
712 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
713 relative->exceptions);
714 }
715 UnlockSemaphoreInfo(relative->semaphore);
716 }
717
718 /*
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720 % %
721 % %
722 % %
723 % I n i t i a l i z e E x c e p t i o n I n f o %
724 % %
725 % %
726 % %
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
728 %
729 % InitializeExceptionInfo() initializes an exception to default values.
730 %
731 % The format of the InitializeExceptionInfo method is:
732 %
733 % InitializeExceptionInfo(ExceptionInfo *exception)
734 %
735 % A description of each parameter follows:
736 %
737 % o exception: the exception info.
738 %
739 */
InitializeExceptionInfo(ExceptionInfo * exception)740 MagickPrivate void InitializeExceptionInfo(ExceptionInfo *exception)
741 {
742 assert(exception != (ExceptionInfo *) NULL);
743 (void) memset(exception,0,sizeof(*exception));
744 exception->severity=UndefinedException;
745 exception->exceptions=(void *) NewLinkedList(0);
746 exception->semaphore=AllocateSemaphoreInfo();
747 exception->signature=MagickCoreSignature;
748 }
749
750 /*
751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
752 % %
753 % %
754 % %
755 % M a g i c k E r r o r %
756 % %
757 % %
758 % %
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760 %
761 % MagickError() calls the exception handler methods with an error reason.
762 %
763 % The format of the MagickError method is:
764 %
765 % void MagickError(const ExceptionType error,const char *reason,
766 % const char *description)
767 %
768 % A description of each parameter follows:
769 %
770 % o exception: Specifies the numeric error category.
771 %
772 % o reason: Specifies the reason to display before terminating the
773 % program.
774 %
775 % o description: Specifies any description to the reason.
776 %
777 */
MagickError(const ExceptionType error,const char * reason,const char * description)778 MagickExport void MagickError(const ExceptionType error,const char *reason,
779 const char *description)
780 {
781 if (error_handler != (ErrorHandler) NULL)
782 (*error_handler)(error,reason,description);
783 }
784
785 /*
786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
787 % %
788 % %
789 % %
790 % M a g i c k F a t al E r r o r %
791 % %
792 % %
793 % %
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 %
796 % MagickFatalError() calls the fatal exception handler methods with an error
797 % reason.
798 %
799 % The format of the MagickError method is:
800 %
801 % void MagickFatalError(const ExceptionType error,const char *reason,
802 % const char *description)
803 %
804 % A description of each parameter follows:
805 %
806 % o exception: Specifies the numeric error category.
807 %
808 % o reason: Specifies the reason to display before terminating the
809 % program.
810 %
811 % o description: Specifies any description to the reason.
812 %
813 */
MagickFatalError(const ExceptionType error,const char * reason,const char * description)814 MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
815 const char *description)
816 {
817 if (fatal_error_handler != (ErrorHandler) NULL)
818 (*fatal_error_handler)(error,reason,description);
819 }
820
821 /*
822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823 % %
824 % %
825 % %
826 % M a g i c k W a r n i n g %
827 % %
828 % %
829 % %
830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831 %
832 % MagickWarning() calls the warning handler methods with a warning reason.
833 %
834 % The format of the MagickWarning method is:
835 %
836 % void MagickWarning(const ExceptionType warning,const char *reason,
837 % const char *description)
838 %
839 % A description of each parameter follows:
840 %
841 % o warning: the warning severity.
842 %
843 % o reason: Define the reason for the warning.
844 %
845 % o description: Describe the warning.
846 %
847 */
MagickWarning(const ExceptionType warning,const char * reason,const char * description)848 MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
849 const char *description)
850 {
851 if (warning_handler != (WarningHandler) NULL)
852 (*warning_handler)(warning,reason,description);
853 }
854
855 /*
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857 % %
858 % %
859 % %
860 % S e t E r r o r H a n d l e r %
861 % %
862 % %
863 % %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865 %
866 % SetErrorHandler() sets the exception handler to the specified method
867 % and returns the previous exception handler.
868 %
869 % The format of the SetErrorHandler method is:
870 %
871 % ErrorHandler SetErrorHandler(ErrorHandler handler)
872 %
873 % A description of each parameter follows:
874 %
875 % o handler: the method to handle errors.
876 %
877 */
SetErrorHandler(ErrorHandler handler)878 MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
879 {
880 ErrorHandler
881 previous_handler;
882
883 if (exception_semaphore == (SemaphoreInfo *) NULL)
884 ActivateSemaphoreInfo(&exception_semaphore);
885 LockSemaphoreInfo(exception_semaphore);
886 previous_handler=error_handler;
887 error_handler=handler;
888 UnlockSemaphoreInfo(exception_semaphore);
889 return(previous_handler);
890 }
891
892 /*
893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
894 % %
895 % %
896 % %
897 % S e t F a t a l E r r o r H a n d l e r %
898 % %
899 % %
900 % %
901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902 %
903 % SetFatalErrorHandler() sets the fatal exception handler to the specified
904 % method and returns the previous fatal exception handler.
905 %
906 % The format of the SetErrorHandler method is:
907 %
908 % ErrorHandler SetErrorHandler(ErrorHandler handler)
909 %
910 % A description of each parameter follows:
911 %
912 % o handler: the method to handle errors.
913 %
914 */
SetFatalErrorHandler(FatalErrorHandler handler)915 MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
916 {
917 FatalErrorHandler
918 previous_handler;
919
920 if (exception_semaphore == (SemaphoreInfo *) NULL)
921 ActivateSemaphoreInfo(&exception_semaphore);
922 LockSemaphoreInfo(exception_semaphore);
923 previous_handler=fatal_error_handler;
924 fatal_error_handler=handler;
925 UnlockSemaphoreInfo(exception_semaphore);
926 return(previous_handler);
927 }
928
929 /*
930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
931 % %
932 % %
933 % %
934 % S e t W a r n i n g H a n d l e r %
935 % %
936 % %
937 % %
938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
939 %
940 % SetWarningHandler() sets the warning handler to the specified method
941 % and returns the previous warning handler.
942 %
943 % The format of the SetWarningHandler method is:
944 %
945 % ErrorHandler SetWarningHandler(ErrorHandler handler)
946 %
947 % A description of each parameter follows:
948 %
949 % o handler: the method to handle warnings.
950 %
951 */
SetWarningHandler(WarningHandler handler)952 MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
953 {
954 WarningHandler
955 previous_handler;
956
957 if (exception_semaphore == (SemaphoreInfo *) NULL)
958 ActivateSemaphoreInfo(&exception_semaphore);
959 LockSemaphoreInfo(exception_semaphore);
960 previous_handler=warning_handler;
961 warning_handler=handler;
962 UnlockSemaphoreInfo(exception_semaphore);
963 return(previous_handler);
964 }
965
966 /*
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968 % %
969 % %
970 % %
971 % T h r o w E x c e p t i o n %
972 % %
973 % %
974 % %
975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976 %
977 % ThrowException() throws an exception with the specified severity code,
978 % reason, and optional description.
979 %
980 % The format of the ThrowException method is:
981 %
982 % MagickBooleanType ThrowException(ExceptionInfo *exception,
983 % const ExceptionType severity,const char *reason,
984 % const char *description)
985 %
986 % A description of each parameter follows:
987 %
988 % o exception: the exception info.
989 %
990 % o severity: the severity of the exception.
991 %
992 % o reason: the reason for the exception.
993 %
994 % o description: the exception description.
995 %
996 */
ThrowException(ExceptionInfo * exception,const ExceptionType severity,const char * reason,const char * description)997 MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception,
998 const ExceptionType severity,const char *reason,const char *description)
999 {
1000 LinkedListInfo
1001 *exceptions;
1002
1003 ExceptionInfo
1004 *p;
1005
1006 assert(exception != (ExceptionInfo *) NULL);
1007 assert(exception->signature == MagickCoreSignature);
1008 LockSemaphoreInfo(exception->semaphore);
1009 exceptions=(LinkedListInfo *) exception->exceptions;
1010 if (GetNumberOfElementsInLinkedList(exceptions) > MaxExceptionList)
1011 {
1012 if (severity < ErrorException)
1013 {
1014 UnlockSemaphoreInfo(exception->semaphore);
1015 return(MagickTrue);
1016 }
1017 p=(ExceptionInfo *) GetLastValueInLinkedList(exceptions);
1018 if (p->severity >= ErrorException)
1019 {
1020 UnlockSemaphoreInfo(exception->semaphore);
1021 return(MagickTrue);
1022 }
1023 }
1024 p=(ExceptionInfo *) GetLastValueInLinkedList(exceptions);
1025 if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) &&
1026 (LocaleCompare(exception->reason,reason) == 0) &&
1027 (LocaleCompare(exception->description,description) == 0))
1028 {
1029 UnlockSemaphoreInfo(exception->semaphore);
1030 return(MagickTrue);
1031 }
1032 p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p));
1033 if (p == (ExceptionInfo *) NULL)
1034 {
1035 UnlockSemaphoreInfo(exception->semaphore);
1036 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1037 }
1038 (void) memset(p,0,sizeof(*p));
1039 p->severity=severity;
1040 if (reason != (const char *) NULL)
1041 p->reason=ConstantString(reason);
1042 if (description != (const char *) NULL)
1043 p->description=ConstantString(description);
1044 p->signature=MagickCoreSignature;
1045 (void) AppendValueToLinkedList(exceptions,p);
1046 if (p->severity > exception->severity)
1047 {
1048 exception->severity=p->severity;
1049 exception->reason=p->reason;
1050 exception->description=p->description;
1051 }
1052 UnlockSemaphoreInfo(exception->semaphore);
1053 if (GetNumberOfElementsInLinkedList(exceptions) == MaxExceptionList)
1054 (void) ThrowMagickException(exception,GetMagickModule(),
1055 ResourceLimitWarning,"TooManyExceptions",
1056 "(exception processing is suspended)");
1057 return(MagickTrue);
1058 }
1059
1060 /*
1061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1062 % %
1063 % %
1064 % %
1065 % T h r o w M a g i c k E x c e p t i o n %
1066 % %
1067 % %
1068 % %
1069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1070 %
1071 % ThrowMagickException logs an exception as determined by the log configuration
1072 % file. If an error occurs, MagickFalse is returned otherwise MagickTrue.
1073 %
1074 % The format of the ThrowMagickException method is:
1075 %
1076 % MagickBooleanType ThrowFileException(ExceptionInfo *exception,
1077 % const char *module,const char *function,const size_t line,
1078 % const ExceptionType severity,const char *tag,const char *format,...)
1079 %
1080 % A description of each parameter follows:
1081 %
1082 % o exception: the exception info.
1083 %
1084 % o filename: the source module filename.
1085 %
1086 % o function: the function name.
1087 %
1088 % o line: the line number of the source module.
1089 %
1090 % o severity: Specifies the numeric error category.
1091 %
1092 % o tag: the locale tag.
1093 %
1094 % o format: the output format.
1095 %
1096 */
1097
ThrowMagickExceptionList(ExceptionInfo * exception,const char * module,const char * function,const size_t line,const ExceptionType severity,const char * tag,const char * format,va_list operands)1098 MagickExport MagickBooleanType ThrowMagickExceptionList(
1099 ExceptionInfo *exception,const char *module,const char *function,
1100 const size_t line,const ExceptionType severity,const char *tag,
1101 const char *format,va_list operands)
1102 {
1103 char
1104 message[MaxTextExtent],
1105 path[MaxTextExtent],
1106 reason[MaxTextExtent];
1107
1108 const char
1109 *locale,
1110 *type;
1111
1112 int
1113 n;
1114
1115 MagickBooleanType
1116 status;
1117
1118 size_t
1119 length;
1120
1121 assert(exception != (ExceptionInfo *) NULL);
1122 assert(exception->signature == MagickCoreSignature);
1123 locale=GetLocaleExceptionMessage(severity,tag);
1124 (void) CopyMagickString(reason,locale,MaxTextExtent);
1125 (void) ConcatenateMagickString(reason," ",MaxTextExtent);
1126 length=strlen(reason);
1127 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
1128 n=vsnprintf(reason+length,MaxTextExtent-length,format,operands);
1129 #else
1130 n=vsprintf(reason+length,format,operands);
1131 #endif
1132 if (n < 0)
1133 reason[MaxTextExtent-1]='\0';
1134 status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason);
1135 GetPathComponent(module,TailPath,path);
1136 type="undefined";
1137 if ((severity >= WarningException) && (severity < ErrorException))
1138 type="warning";
1139 if ((severity >= ErrorException) && (severity < FatalErrorException))
1140 type="error";
1141 if (severity >= FatalErrorException)
1142 type="fatal";
1143 (void) FormatLocaleString(message,MaxTextExtent,"%s @ %s/%s/%s/%.20g",reason,
1144 type,path,function,(double) line);
1145 (void) ThrowException(exception,severity,message,(char *) NULL);
1146 return(status);
1147 }
1148
ThrowMagickException(ExceptionInfo * exception,const char * module,const char * function,const size_t line,const ExceptionType severity,const char * tag,const char * format,...)1149 MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception,
1150 const char *module,const char *function,const size_t line,
1151 const ExceptionType severity,const char *tag,const char *format,...)
1152 {
1153 MagickBooleanType
1154 status;
1155
1156 va_list
1157 operands;
1158
1159 va_start(operands,format);
1160 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,
1161 format,operands);
1162 va_end(operands);
1163 return(status);
1164 }
1165