pngerror.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. /* pngerror.c - stub functions for i/o and memory allocation
  2. *
  3. * Copyright (c) 2018-2025 Cosmin Truta
  4. * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
  5. * Copyright (c) 1996-1997 Andreas Dilger
  6. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
  7. *
  8. * This code is released under the libpng license.
  9. * For conditions of distribution and use, see the disclaimer
  10. * and license in png.h
  11. *
  12. * This file provides a location for all error handling. Users who
  13. * need special error handling are expected to write replacement functions
  14. * and use png_set_error_fn() to use those functions. See the instructions
  15. * at each function.
  16. */
  17. #include "pngpriv.h"
  18. #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
  19. static PNG_FUNCTION(void /* PRIVATE */,
  20. png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
  21. PNG_NORETURN);
  22. #ifdef PNG_WARNINGS_SUPPORTED
  23. static void /* PRIVATE */
  24. png_default_warning(png_const_structrp png_ptr,
  25. png_const_charp warning_message);
  26. #endif /* WARNINGS */
  27. /* This function is called whenever there is a fatal error. This function
  28. * should not be changed. If there is a need to handle errors differently,
  29. * you should supply a replacement error function and use png_set_error_fn()
  30. * to replace the error function at run-time.
  31. */
  32. #ifdef PNG_ERROR_TEXT_SUPPORTED
  33. PNG_FUNCTION(void,PNGAPI
  34. png_error,(png_const_structrp png_ptr, png_const_charp error_message),
  35. PNG_NORETURN)
  36. {
  37. if (png_ptr != NULL && png_ptr->error_fn != NULL)
  38. (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
  39. error_message);
  40. /* If the custom handler doesn't exist, or if it returns,
  41. use the default handler, which will not return. */
  42. png_default_error(png_ptr, error_message);
  43. }
  44. #else
  45. PNG_FUNCTION(void,PNGAPI
  46. png_err,(png_const_structrp png_ptr),PNG_NORETURN)
  47. {
  48. /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
  49. * erroneously as '\0', instead of the empty string "". This was
  50. * apparently an error, introduced in libpng-1.2.20, and png_default_error
  51. * will crash in this case.
  52. */
  53. if (png_ptr != NULL && png_ptr->error_fn != NULL)
  54. (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), "");
  55. /* If the custom handler doesn't exist, or if it returns,
  56. use the default handler, which will not return. */
  57. png_default_error(png_ptr, "");
  58. }
  59. #endif /* ERROR_TEXT */
  60. /* Utility to safely appends strings to a buffer. This never errors out so
  61. * error checking is not required in the caller.
  62. */
  63. size_t
  64. png_safecat(png_charp buffer, size_t bufsize, size_t pos,
  65. png_const_charp string)
  66. {
  67. if (buffer != NULL && pos < bufsize)
  68. {
  69. if (string != NULL)
  70. while (*string != '\0' && pos < bufsize-1)
  71. buffer[pos++] = *string++;
  72. buffer[pos] = '\0';
  73. }
  74. return pos;
  75. }
  76. #if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
  77. /* Utility to dump an unsigned value into a buffer, given a start pointer and
  78. * and end pointer (which should point just *beyond* the end of the buffer!)
  79. * Returns the pointer to the start of the formatted string.
  80. */
  81. png_charp
  82. png_format_number(png_const_charp start, png_charp end, int format,
  83. png_alloc_size_t number)
  84. {
  85. int count = 0; /* number of digits output */
  86. int mincount = 1; /* minimum number required */
  87. int output = 0; /* digit output (for the fixed point format) */
  88. *--end = '\0';
  89. /* This is written so that the loop always runs at least once, even with
  90. * number zero.
  91. */
  92. while (end > start && (number != 0 || count < mincount))
  93. {
  94. static const char digits[] = "0123456789ABCDEF";
  95. switch (format)
  96. {
  97. case PNG_NUMBER_FORMAT_fixed:
  98. /* Needs five digits (the fraction) */
  99. mincount = 5;
  100. if (output != 0 || number % 10 != 0)
  101. {
  102. *--end = digits[number % 10];
  103. output = 1;
  104. }
  105. number /= 10;
  106. break;
  107. case PNG_NUMBER_FORMAT_02u:
  108. /* Expects at least 2 digits. */
  109. mincount = 2;
  110. /* FALLTHROUGH */
  111. case PNG_NUMBER_FORMAT_u:
  112. *--end = digits[number % 10];
  113. number /= 10;
  114. break;
  115. case PNG_NUMBER_FORMAT_02x:
  116. /* This format expects at least two digits */
  117. mincount = 2;
  118. /* FALLTHROUGH */
  119. case PNG_NUMBER_FORMAT_x:
  120. *--end = digits[number & 0xf];
  121. number >>= 4;
  122. break;
  123. default: /* an error */
  124. number = 0;
  125. break;
  126. }
  127. /* Keep track of the number of digits added */
  128. ++count;
  129. /* Float a fixed number here: */
  130. if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
  131. {
  132. /* End of the fraction, but maybe nothing was output? In that case
  133. * drop the decimal point. If the number is a true zero handle that
  134. * here.
  135. */
  136. if (output != 0)
  137. *--end = '.';
  138. else if (number == 0) /* and !output */
  139. *--end = '0';
  140. }
  141. }
  142. return end;
  143. }
  144. #endif
  145. #ifdef PNG_WARNINGS_SUPPORTED
  146. /* This function is called whenever there is a non-fatal error. This function
  147. * should not be changed. If there is a need to handle warnings differently,
  148. * you should supply a replacement warning function and use
  149. * png_set_error_fn() to replace the warning function at run-time.
  150. */
  151. void PNGAPI
  152. png_warning(png_const_structrp png_ptr, png_const_charp warning_message)
  153. {
  154. int offset = 0;
  155. if (png_ptr != NULL && png_ptr->warning_fn != NULL)
  156. (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
  157. warning_message + offset);
  158. else
  159. png_default_warning(png_ptr, warning_message + offset);
  160. }
  161. /* These functions support 'formatted' warning messages with up to
  162. * PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter
  163. * is introduced by @<number>, where 'number' starts at 1. This follows the
  164. * standard established by X/Open for internationalizable error messages.
  165. */
  166. void
  167. png_warning_parameter(png_warning_parameters p, int number,
  168. png_const_charp string)
  169. {
  170. if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT)
  171. (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string);
  172. }
  173. void
  174. png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
  175. png_alloc_size_t value)
  176. {
  177. char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
  178. png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
  179. }
  180. void
  181. png_warning_parameter_signed(png_warning_parameters p, int number, int format,
  182. png_int_32 value)
  183. {
  184. png_alloc_size_t u;
  185. png_charp str;
  186. char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
  187. /* Avoid overflow by doing the negate in a png_alloc_size_t: */
  188. u = (png_alloc_size_t)value;
  189. if (value < 0)
  190. u = ~u + 1;
  191. str = PNG_FORMAT_NUMBER(buffer, format, u);
  192. if (value < 0 && str > buffer)
  193. *--str = '-';
  194. png_warning_parameter(p, number, str);
  195. }
  196. void
  197. png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p,
  198. png_const_charp message)
  199. {
  200. /* The internal buffer is just 192 bytes - enough for all our messages,
  201. * overflow doesn't happen because this code checks! If someone figures
  202. * out how to send us a message longer than 192 bytes, all that will
  203. * happen is that the message will be truncated appropriately.
  204. */
  205. size_t i = 0; /* Index in the msg[] buffer: */
  206. char msg[192];
  207. /* Each iteration through the following loop writes at most one character
  208. * to msg[i++] then returns here to validate that there is still space for
  209. * the trailing '\0'. It may (in the case of a parameter) read more than
  210. * one character from message[]; it must check for '\0' and continue to the
  211. * test if it finds the end of string.
  212. */
  213. while (i<(sizeof msg)-1 && *message != '\0')
  214. {
  215. /* '@' at end of string is now just printed (previously it was skipped);
  216. * it is an error in the calling code to terminate the string with @.
  217. */
  218. if (p != NULL && *message == '@' && message[1] != '\0')
  219. {
  220. int parameter_char = *++message; /* Consume the '@' */
  221. static const char valid_parameters[] = "123456789";
  222. int parameter = 0;
  223. /* Search for the parameter digit, the index in the string is the
  224. * parameter to use.
  225. */
  226. while (valid_parameters[parameter] != parameter_char &&
  227. valid_parameters[parameter] != '\0')
  228. ++parameter;
  229. /* If the parameter digit is out of range it will just get printed. */
  230. if (parameter < PNG_WARNING_PARAMETER_COUNT)
  231. {
  232. /* Append this parameter */
  233. png_const_charp parm = p[parameter];
  234. png_const_charp pend = p[parameter] + (sizeof p[parameter]);
  235. /* No need to copy the trailing '\0' here, but there is no guarantee
  236. * that parm[] has been initialized, so there is no guarantee of a
  237. * trailing '\0':
  238. */
  239. while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
  240. msg[i++] = *parm++;
  241. /* Consume the parameter digit too: */
  242. ++message;
  243. continue;
  244. }
  245. /* else not a parameter and there is a character after the @ sign; just
  246. * copy that. This is known not to be '\0' because of the test above.
  247. */
  248. }
  249. /* At this point *message can't be '\0', even in the bad parameter case
  250. * above where there is a lone '@' at the end of the message string.
  251. */
  252. msg[i++] = *message++;
  253. }
  254. /* i is always less than (sizeof msg), so: */
  255. msg[i] = '\0';
  256. /* And this is the formatted message. It may be larger than
  257. * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
  258. * are not (currently) formatted.
  259. */
  260. png_warning(png_ptr, msg);
  261. }
  262. #endif /* WARNINGS */
  263. #ifdef PNG_BENIGN_ERRORS_SUPPORTED
  264. void PNGAPI
  265. png_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
  266. {
  267. if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
  268. {
  269. # ifdef PNG_READ_SUPPORTED
  270. if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
  271. png_ptr->chunk_name != 0)
  272. png_chunk_warning(png_ptr, error_message);
  273. else
  274. # endif
  275. png_warning(png_ptr, error_message);
  276. }
  277. else
  278. {
  279. # ifdef PNG_READ_SUPPORTED
  280. if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
  281. png_ptr->chunk_name != 0)
  282. png_chunk_error(png_ptr, error_message);
  283. else
  284. # endif
  285. png_error(png_ptr, error_message);
  286. }
  287. # ifndef PNG_ERROR_TEXT_SUPPORTED
  288. PNG_UNUSED(error_message)
  289. # endif
  290. }
  291. void /* PRIVATE */
  292. png_app_warning(png_const_structrp png_ptr, png_const_charp error_message)
  293. {
  294. if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0)
  295. png_warning(png_ptr, error_message);
  296. else
  297. png_error(png_ptr, error_message);
  298. # ifndef PNG_ERROR_TEXT_SUPPORTED
  299. PNG_UNUSED(error_message)
  300. # endif
  301. }
  302. void /* PRIVATE */
  303. png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
  304. {
  305. if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0)
  306. png_warning(png_ptr, error_message);
  307. else
  308. png_error(png_ptr, error_message);
  309. # ifndef PNG_ERROR_TEXT_SUPPORTED
  310. PNG_UNUSED(error_message)
  311. # endif
  312. }
  313. #endif /* BENIGN_ERRORS */
  314. #define PNG_MAX_ERROR_TEXT 196 /* Currently limited by profile_error in png.c */
  315. #if defined(PNG_WARNINGS_SUPPORTED) || \
  316. (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED))
  317. /* These utilities are used internally to build an error message that relates
  318. * to the current chunk. The chunk name comes from png_ptr->chunk_name,
  319. * which is used to prefix the message. The message is limited in length
  320. * to 63 bytes. The name characters are output as hex digits wrapped in []
  321. * if the character is invalid.
  322. */
  323. #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
  324. static const char png_digit[16] = {
  325. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  326. 'A', 'B', 'C', 'D', 'E', 'F'
  327. };
  328. static void /* PRIVATE */
  329. png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
  330. error_message)
  331. {
  332. png_uint_32 chunk_name = png_ptr->chunk_name;
  333. int iout = 0, ishift = 24;
  334. while (ishift >= 0)
  335. {
  336. int c = (int)(chunk_name >> ishift) & 0xff;
  337. ishift -= 8;
  338. if (isnonalpha(c) != 0)
  339. {
  340. buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
  341. buffer[iout++] = png_digit[(c & 0xf0) >> 4];
  342. buffer[iout++] = png_digit[c & 0x0f];
  343. buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET;
  344. }
  345. else
  346. {
  347. buffer[iout++] = (char)c;
  348. }
  349. }
  350. if (error_message == NULL)
  351. buffer[iout] = '\0';
  352. else
  353. {
  354. int iin = 0;
  355. buffer[iout++] = ':';
  356. buffer[iout++] = ' ';
  357. while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
  358. buffer[iout++] = error_message[iin++];
  359. /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */
  360. buffer[iout] = '\0';
  361. }
  362. }
  363. #endif /* WARNINGS || ERROR_TEXT */
  364. #if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
  365. PNG_FUNCTION(void,PNGAPI
  366. png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message),
  367. PNG_NORETURN)
  368. {
  369. char msg[18+PNG_MAX_ERROR_TEXT];
  370. if (png_ptr == NULL)
  371. png_error(png_ptr, error_message);
  372. else
  373. {
  374. png_format_buffer(png_ptr, msg, error_message);
  375. png_error(png_ptr, msg);
  376. }
  377. }
  378. #endif /* READ && ERROR_TEXT */
  379. #ifdef PNG_WARNINGS_SUPPORTED
  380. void PNGAPI
  381. png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message)
  382. {
  383. char msg[18+PNG_MAX_ERROR_TEXT];
  384. if (png_ptr == NULL)
  385. png_warning(png_ptr, warning_message);
  386. else
  387. {
  388. png_format_buffer(png_ptr, msg, warning_message);
  389. png_warning(png_ptr, msg);
  390. }
  391. }
  392. #endif /* WARNINGS */
  393. #ifdef PNG_READ_SUPPORTED
  394. #ifdef PNG_BENIGN_ERRORS_SUPPORTED
  395. void PNGAPI
  396. png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
  397. error_message)
  398. {
  399. if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
  400. png_chunk_warning(png_ptr, error_message);
  401. else
  402. png_chunk_error(png_ptr, error_message);
  403. # ifndef PNG_ERROR_TEXT_SUPPORTED
  404. PNG_UNUSED(error_message)
  405. # endif
  406. }
  407. #endif
  408. #endif /* READ */
  409. void /* PRIVATE */
  410. png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
  411. {
  412. # ifndef PNG_WARNINGS_SUPPORTED
  413. PNG_UNUSED(message)
  414. # endif
  415. /* This is always supported, but for just read or just write it
  416. * unconditionally does the right thing.
  417. */
  418. # if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
  419. if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
  420. # endif
  421. # ifdef PNG_READ_SUPPORTED
  422. {
  423. if (error < PNG_CHUNK_ERROR)
  424. png_chunk_warning(png_ptr, message);
  425. else
  426. png_chunk_benign_error(png_ptr, message);
  427. }
  428. # endif
  429. # if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
  430. else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
  431. # endif
  432. # ifdef PNG_WRITE_SUPPORTED
  433. {
  434. if (error < PNG_CHUNK_WRITE_ERROR)
  435. png_app_warning(png_ptr, message);
  436. else
  437. png_app_error(png_ptr, message);
  438. }
  439. # endif
  440. }
  441. #ifdef PNG_ERROR_TEXT_SUPPORTED
  442. #ifdef PNG_FLOATING_POINT_SUPPORTED
  443. PNG_FUNCTION(void,
  444. png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
  445. {
  446. # define fixed_message "fixed point overflow in "
  447. # define fixed_message_ln ((sizeof fixed_message)-1)
  448. unsigned int iin;
  449. char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
  450. memcpy(msg, fixed_message, fixed_message_ln);
  451. iin = 0;
  452. if (name != NULL)
  453. while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
  454. {
  455. msg[fixed_message_ln + iin] = name[iin];
  456. ++iin;
  457. }
  458. msg[fixed_message_ln + iin] = 0;
  459. png_error(png_ptr, msg);
  460. }
  461. #endif
  462. #endif
  463. #ifdef PNG_SETJMP_SUPPORTED
  464. /* This API only exists if ANSI-C style error handling is used,
  465. * otherwise it is necessary for png_default_error to be overridden.
  466. */
  467. jmp_buf* PNGAPI
  468. png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn,
  469. size_t jmp_buf_size)
  470. {
  471. /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
  472. * and it must not change after that. Libpng doesn't care how big the
  473. * buffer is, just that it doesn't change.
  474. *
  475. * If the buffer size is no *larger* than the size of jmp_buf when libpng is
  476. * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
  477. * semantics that this call will not fail. If the size is larger, however,
  478. * the buffer is allocated and this may fail, causing the function to return
  479. * NULL.
  480. */
  481. if (png_ptr == NULL)
  482. return NULL;
  483. if (png_ptr->jmp_buf_ptr == NULL)
  484. {
  485. png_ptr->jmp_buf_size = 0; /* not allocated */
  486. if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
  487. png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
  488. else
  489. {
  490. png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *,
  491. png_malloc_warn(png_ptr, jmp_buf_size));
  492. if (png_ptr->jmp_buf_ptr == NULL)
  493. return NULL; /* new NULL return on OOM */
  494. png_ptr->jmp_buf_size = jmp_buf_size;
  495. }
  496. }
  497. else /* Already allocated: check the size */
  498. {
  499. size_t size = png_ptr->jmp_buf_size;
  500. if (size == 0)
  501. {
  502. size = (sizeof png_ptr->jmp_buf_local);
  503. if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
  504. {
  505. /* This is an internal error in libpng: somehow we have been left
  506. * with a stack allocated jmp_buf when the application regained
  507. * control. It's always possible to fix this up, but for the moment
  508. * this is a png_error because that makes it easy to detect.
  509. */
  510. png_error(png_ptr, "Libpng jmp_buf still allocated");
  511. /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
  512. }
  513. }
  514. if (size != jmp_buf_size)
  515. {
  516. png_warning(png_ptr, "Application jmp_buf size changed");
  517. return NULL; /* caller will probably crash: no choice here */
  518. }
  519. }
  520. /* Finally fill in the function, now we have a satisfactory buffer. It is
  521. * valid to change the function on every call.
  522. */
  523. png_ptr->longjmp_fn = longjmp_fn;
  524. return png_ptr->jmp_buf_ptr;
  525. }
  526. void /* PRIVATE */
  527. png_free_jmpbuf(png_structrp png_ptr)
  528. {
  529. if (png_ptr != NULL)
  530. {
  531. jmp_buf *jb = png_ptr->jmp_buf_ptr;
  532. /* A size of 0 is used to indicate a local, stack, allocation of the
  533. * pointer; used here and in png.c
  534. */
  535. if (jb != NULL && png_ptr->jmp_buf_size > 0)
  536. {
  537. /* This stuff is so that a failure to free the error control structure
  538. * does not leave libpng in a state with no valid error handling: the
  539. * free always succeeds, if there is an error it gets ignored.
  540. */
  541. if (jb != &png_ptr->jmp_buf_local)
  542. {
  543. /* Make an internal, libpng, jmp_buf to return here */
  544. jmp_buf free_jmp_buf;
  545. if (!setjmp(free_jmp_buf))
  546. {
  547. png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
  548. png_ptr->jmp_buf_size = 0; /* stack allocation */
  549. png_ptr->longjmp_fn = longjmp;
  550. png_free(png_ptr, jb); /* Return to setjmp on error */
  551. }
  552. }
  553. }
  554. /* *Always* cancel everything out: */
  555. png_ptr->jmp_buf_size = 0;
  556. png_ptr->jmp_buf_ptr = NULL;
  557. png_ptr->longjmp_fn = 0;
  558. }
  559. }
  560. #endif
  561. /* This is the default error handling function. Note that replacements for
  562. * this function MUST NOT RETURN, or the program will likely crash. This
  563. * function is used by default, or if the program supplies NULL for the
  564. * error function pointer in png_set_error_fn().
  565. */
  566. static PNG_FUNCTION(void /* PRIVATE */,
  567. png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
  568. PNG_NORETURN)
  569. {
  570. #ifdef PNG_CONSOLE_IO_SUPPORTED
  571. fprintf(stderr, "libpng error: %s", error_message ? error_message :
  572. "undefined");
  573. fprintf(stderr, PNG_STRING_NEWLINE);
  574. #else
  575. PNG_UNUSED(error_message) /* Make compiler happy */
  576. #endif
  577. png_longjmp(png_ptr, 1);
  578. }
  579. PNG_FUNCTION(void,PNGAPI
  580. png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN)
  581. {
  582. #ifdef PNG_SETJMP_SUPPORTED
  583. if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
  584. png_ptr->jmp_buf_ptr != NULL)
  585. png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val);
  586. #else
  587. PNG_UNUSED(png_ptr)
  588. PNG_UNUSED(val)
  589. #endif
  590. /* If control reaches this point, png_longjmp() must not return. The only
  591. * choice is to terminate the whole process (or maybe the thread); to do
  592. * this the ANSI-C abort() function is used unless a different method is
  593. * implemented by overriding the default configuration setting for
  594. * PNG_ABORT().
  595. */
  596. PNG_ABORT();
  597. }
  598. #ifdef PNG_WARNINGS_SUPPORTED
  599. /* This function is called when there is a warning, but the library thinks
  600. * it can continue anyway. Replacement functions don't have to do anything
  601. * here if you don't want them to. In the default configuration, png_ptr is
  602. * not used, but it is passed in case it may be useful.
  603. */
  604. static void /* PRIVATE */
  605. png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
  606. {
  607. #ifdef PNG_CONSOLE_IO_SUPPORTED
  608. fprintf(stderr, "libpng warning: %s", warning_message);
  609. fprintf(stderr, PNG_STRING_NEWLINE);
  610. #else
  611. PNG_UNUSED(warning_message) /* Make compiler happy */
  612. #endif
  613. PNG_UNUSED(png_ptr) /* Make compiler happy */
  614. }
  615. #endif /* WARNINGS */
  616. /* This function is called when the application wants to use another method
  617. * of handling errors and warnings. Note that the error function MUST NOT
  618. * return to the calling routine or serious problems will occur. The return
  619. * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
  620. */
  621. void PNGAPI
  622. png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr,
  623. png_error_ptr error_fn, png_error_ptr warning_fn)
  624. {
  625. if (png_ptr == NULL)
  626. return;
  627. png_ptr->error_ptr = error_ptr;
  628. png_ptr->error_fn = error_fn;
  629. #ifdef PNG_WARNINGS_SUPPORTED
  630. png_ptr->warning_fn = warning_fn;
  631. #else
  632. PNG_UNUSED(warning_fn)
  633. #endif
  634. }
  635. /* This function returns a pointer to the error_ptr associated with the user
  636. * functions. The application should free any memory associated with this
  637. * pointer before png_write_destroy and png_read_destroy are called.
  638. */
  639. png_voidp PNGAPI
  640. png_get_error_ptr(png_const_structrp png_ptr)
  641. {
  642. if (png_ptr == NULL)
  643. return NULL;
  644. return (png_voidp)png_ptr->error_ptr;
  645. }
  646. #ifdef PNG_ERROR_NUMBERS_SUPPORTED
  647. void PNGAPI
  648. png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
  649. {
  650. PNG_UNUSED(png_ptr)
  651. PNG_UNUSED(strip_mode)
  652. }
  653. #endif
  654. #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
  655. defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
  656. /* Currently the above both depend on SETJMP_SUPPORTED, however it would be
  657. * possible to implement without setjmp support just so long as there is some
  658. * way to handle the error return here:
  659. */
  660. PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
  661. png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
  662. PNG_NORETURN)
  663. {
  664. png_const_structrp png_ptr = png_nonconst_ptr;
  665. png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
  666. /* An error is always logged here, overwriting anything (typically a warning)
  667. * that is already there:
  668. */
  669. if (image != NULL)
  670. {
  671. png_safecat(image->message, (sizeof image->message), 0, error_message);
  672. image->warning_or_error |= PNG_IMAGE_ERROR;
  673. /* Retrieve the jmp_buf from within the png_control, making this work for
  674. * C++ compilation too is pretty tricky: C++ wants a pointer to the first
  675. * element of a jmp_buf, but C doesn't tell us the type of that.
  676. */
  677. if (image->opaque != NULL && image->opaque->error_buf != NULL)
  678. longjmp(png_control_jmp_buf(image->opaque), 1);
  679. /* Missing longjmp buffer, the following is to help debugging: */
  680. {
  681. size_t pos = png_safecat(image->message, (sizeof image->message), 0,
  682. "bad longjmp: ");
  683. png_safecat(image->message, (sizeof image->message), pos,
  684. error_message);
  685. }
  686. }
  687. /* Here on an internal programming error. */
  688. abort();
  689. }
  690. #ifdef PNG_WARNINGS_SUPPORTED
  691. void /* PRIVATE */ PNGCBAPI
  692. png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
  693. {
  694. png_const_structrp png_ptr = png_nonconst_ptr;
  695. png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
  696. /* A warning is only logged if there is no prior warning or error. */
  697. if (image->warning_or_error == 0)
  698. {
  699. png_safecat(image->message, (sizeof image->message), 0, warning_message);
  700. image->warning_or_error |= PNG_IMAGE_WARNING;
  701. }
  702. }
  703. #endif
  704. int /* PRIVATE */
  705. png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg)
  706. {
  707. const png_voidp saved_error_buf = image->opaque->error_buf;
  708. jmp_buf safe_jmpbuf;
  709. /* Safely execute function(arg), with png_error returning back here. */
  710. if (setjmp(safe_jmpbuf) == 0)
  711. {
  712. int result;
  713. image->opaque->error_buf = safe_jmpbuf;
  714. result = function(arg);
  715. image->opaque->error_buf = saved_error_buf;
  716. if (result)
  717. return 1; /* success */
  718. }
  719. /* The function failed either because of a caught png_error and a regular
  720. * return of false above or because of an uncaught png_error from the
  721. * function itself. Ensure that the error_buf is always set back to the
  722. * value saved above:
  723. */
  724. image->opaque->error_buf = saved_error_buf;
  725. /* On the final false return, when about to return control to the caller, the
  726. * image is freed (png_image_free does this check but it is duplicated here
  727. * for clarity:
  728. */
  729. if (saved_error_buf == NULL)
  730. png_image_free(image);
  731. return 0; /* failure */
  732. }
  733. #endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
  734. #endif /* READ || WRITE */