zend_exceptions.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@php.net> |
  16. | Marcus Boerger <helly@php.net> |
  17. | Sterling Hughes <sterling@php.net> |
  18. | Zeev Suraski <zeev@php.net> |
  19. +----------------------------------------------------------------------+
  20. */
  21. #include "zend.h"
  22. #include "zend_API.h"
  23. #include "zend_builtin_functions.h"
  24. #include "zend_interfaces.h"
  25. #include "zend_exceptions.h"
  26. #include "zend_vm.h"
  27. #include "zend_dtrace.h"
  28. #include "zend_smart_str.h"
  29. ZEND_API zend_class_entry *zend_ce_throwable;
  30. ZEND_API zend_class_entry *zend_ce_exception;
  31. ZEND_API zend_class_entry *zend_ce_error_exception;
  32. ZEND_API zend_class_entry *zend_ce_error;
  33. ZEND_API zend_class_entry *zend_ce_compile_error;
  34. ZEND_API zend_class_entry *zend_ce_parse_error;
  35. ZEND_API zend_class_entry *zend_ce_type_error;
  36. ZEND_API zend_class_entry *zend_ce_argument_count_error;
  37. ZEND_API zend_class_entry *zend_ce_arithmetic_error;
  38. ZEND_API zend_class_entry *zend_ce_division_by_zero_error;
  39. ZEND_API void (*zend_throw_exception_hook)(zval *ex);
  40. static zend_object_handlers default_exception_handlers;
  41. /* {{{ zend_implement_throwable */
  42. static int zend_implement_throwable(zend_class_entry *interface, zend_class_entry *class_type)
  43. {
  44. if (instanceof_function(class_type, zend_ce_exception) || instanceof_function(class_type, zend_ce_error)) {
  45. return SUCCESS;
  46. }
  47. zend_error_noreturn(E_ERROR, "Class %s cannot implement interface %s, extend %s or %s instead",
  48. ZSTR_VAL(class_type->name),
  49. ZSTR_VAL(interface->name),
  50. ZSTR_VAL(zend_ce_exception->name),
  51. ZSTR_VAL(zend_ce_error->name));
  52. return FAILURE;
  53. }
  54. /* }}} */
  55. static inline zend_class_entry *i_get_exception_base(zval *object) /* {{{ */
  56. {
  57. return instanceof_function(Z_OBJCE_P(object), zend_ce_exception) ? zend_ce_exception : zend_ce_error;
  58. }
  59. /* }}} */
  60. ZEND_API zend_class_entry *zend_get_exception_base(zval *object) /* {{{ */
  61. {
  62. return i_get_exception_base(object);
  63. }
  64. /* }}} */
  65. void zend_exception_set_previous(zend_object *exception, zend_object *add_previous) /* {{{ */
  66. {
  67. zval *previous, *ancestor, *ex;
  68. zval pv, zv, rv;
  69. zend_class_entry *base_ce;
  70. if (!exception || !add_previous) {
  71. return;
  72. }
  73. if (exception == add_previous) {
  74. OBJ_RELEASE(add_previous);
  75. return;
  76. }
  77. ZVAL_OBJ(&pv, add_previous);
  78. if (!instanceof_function(Z_OBJCE(pv), zend_ce_throwable)) {
  79. zend_error_noreturn(E_CORE_ERROR, "Previous exception must implement Throwable");
  80. return;
  81. }
  82. ZVAL_OBJ(&zv, exception);
  83. ex = &zv;
  84. do {
  85. ancestor = zend_read_property_ex(i_get_exception_base(&pv), &pv, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
  86. while (Z_TYPE_P(ancestor) == IS_OBJECT) {
  87. if (Z_OBJ_P(ancestor) == Z_OBJ_P(ex)) {
  88. OBJ_RELEASE(add_previous);
  89. return;
  90. }
  91. ancestor = zend_read_property_ex(i_get_exception_base(ancestor), ancestor, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
  92. }
  93. base_ce = i_get_exception_base(ex);
  94. previous = zend_read_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
  95. if (Z_TYPE_P(previous) == IS_NULL) {
  96. zend_update_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), &pv);
  97. GC_DELREF(add_previous);
  98. return;
  99. }
  100. ex = previous;
  101. } while (Z_OBJ_P(ex) != add_previous);
  102. }
  103. /* }}} */
  104. void zend_exception_save(void) /* {{{ */
  105. {
  106. if (EG(prev_exception)) {
  107. zend_exception_set_previous(EG(exception), EG(prev_exception));
  108. }
  109. if (EG(exception)) {
  110. EG(prev_exception) = EG(exception);
  111. }
  112. EG(exception) = NULL;
  113. }
  114. /* }}} */
  115. void zend_exception_restore(void) /* {{{ */
  116. {
  117. if (EG(prev_exception)) {
  118. if (EG(exception)) {
  119. zend_exception_set_previous(EG(exception), EG(prev_exception));
  120. } else {
  121. EG(exception) = EG(prev_exception);
  122. }
  123. EG(prev_exception) = NULL;
  124. }
  125. }
  126. /* }}} */
  127. ZEND_API ZEND_COLD void zend_throw_exception_internal(zval *exception) /* {{{ */
  128. {
  129. #ifdef HAVE_DTRACE
  130. if (DTRACE_EXCEPTION_THROWN_ENABLED()) {
  131. if (exception != NULL) {
  132. DTRACE_EXCEPTION_THROWN(ZSTR_VAL(Z_OBJ_P(exception)->ce->name));
  133. } else {
  134. DTRACE_EXCEPTION_THROWN(NULL);
  135. }
  136. }
  137. #endif /* HAVE_DTRACE */
  138. if (exception != NULL) {
  139. zend_object *previous = EG(exception);
  140. zend_exception_set_previous(Z_OBJ_P(exception), EG(exception));
  141. EG(exception) = Z_OBJ_P(exception);
  142. if (previous) {
  143. return;
  144. }
  145. }
  146. if (!EG(current_execute_data)) {
  147. if (exception && (Z_OBJCE_P(exception) == zend_ce_parse_error || Z_OBJCE_P(exception) == zend_ce_compile_error)) {
  148. return;
  149. }
  150. if(EG(exception)) {
  151. zend_exception_error(EG(exception), E_ERROR);
  152. }
  153. zend_error_noreturn(E_CORE_ERROR, "Exception thrown without a stack frame");
  154. }
  155. if (zend_throw_exception_hook) {
  156. zend_throw_exception_hook(exception);
  157. }
  158. if (!EG(current_execute_data)->func ||
  159. !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
  160. EG(current_execute_data)->opline->opcode == ZEND_HANDLE_EXCEPTION) {
  161. /* no need to rethrow the exception */
  162. return;
  163. }
  164. EG(opline_before_exception) = EG(current_execute_data)->opline;
  165. EG(current_execute_data)->opline = EG(exception_op);
  166. }
  167. /* }}} */
  168. ZEND_API void zend_clear_exception(void) /* {{{ */
  169. {
  170. if (EG(prev_exception)) {
  171. OBJ_RELEASE(EG(prev_exception));
  172. EG(prev_exception) = NULL;
  173. }
  174. if (!EG(exception)) {
  175. return;
  176. }
  177. OBJ_RELEASE(EG(exception));
  178. EG(exception) = NULL;
  179. if (EG(current_execute_data)) {
  180. EG(current_execute_data)->opline = EG(opline_before_exception);
  181. }
  182. #if ZEND_DEBUG
  183. EG(opline_before_exception) = NULL;
  184. #endif
  185. }
  186. /* }}} */
  187. static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces) /* {{{ */
  188. {
  189. zval obj, tmp;
  190. zend_object *object;
  191. zval trace;
  192. zend_class_entry *base_ce;
  193. zend_string *filename;
  194. Z_OBJ(obj) = object = zend_objects_new(class_type);
  195. Z_OBJ_HT(obj) = &default_exception_handlers;
  196. object_properties_init(object, class_type);
  197. if (EG(current_execute_data)) {
  198. zend_fetch_debug_backtrace(&trace, skip_top_traces, 0, 0);
  199. } else {
  200. array_init(&trace);
  201. }
  202. Z_SET_REFCOUNT(trace, 0);
  203. base_ce = i_get_exception_base(&obj);
  204. if (EXPECTED((class_type != zend_ce_parse_error && class_type != zend_ce_compile_error)
  205. || !(filename = zend_get_compiled_filename()))) {
  206. ZVAL_STRING(&tmp, zend_get_executed_filename());
  207. zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
  208. zval_ptr_dtor(&tmp);
  209. ZVAL_LONG(&tmp, zend_get_executed_lineno());
  210. zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
  211. } else {
  212. ZVAL_STR(&tmp, filename);
  213. zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
  214. ZVAL_LONG(&tmp, zend_get_compiled_lineno());
  215. zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
  216. }
  217. zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_TRACE), &trace);
  218. return object;
  219. }
  220. /* }}} */
  221. static zend_object *zend_default_exception_new(zend_class_entry *class_type) /* {{{ */
  222. {
  223. return zend_default_exception_new_ex(class_type, 0);
  224. }
  225. /* }}} */
  226. static zend_object *zend_error_exception_new(zend_class_entry *class_type) /* {{{ */
  227. {
  228. return zend_default_exception_new_ex(class_type, 2);
  229. }
  230. /* }}} */
  231. /* {{{ proto Exception|Error Exception|Error::__clone()
  232. Clone the exception object */
  233. ZEND_COLD ZEND_METHOD(exception, __clone)
  234. {
  235. /* Should never be executable */
  236. zend_throw_exception(NULL, "Cannot clone object using __clone()", 0);
  237. }
  238. /* }}} */
  239. /* {{{ proto Exception|Error::__construct(string message, int code [, Throwable previous])
  240. Exception constructor */
  241. ZEND_METHOD(exception, __construct)
  242. {
  243. zend_string *message = NULL;
  244. zend_long code = 0;
  245. zval tmp, *object, *previous = NULL;
  246. zend_class_entry *base_ce;
  247. int argc = ZEND_NUM_ARGS();
  248. object = getThis();
  249. base_ce = i_get_exception_base(object);
  250. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, zend_ce_throwable) == FAILURE) {
  251. zend_class_entry *ce;
  252. if (Z_TYPE(EX(This)) == IS_OBJECT) {
  253. ce = Z_OBJCE(EX(This));
  254. } else if (Z_CE(EX(This))) {
  255. ce = Z_CE(EX(This));
  256. } else {
  257. ce = base_ce;
  258. }
  259. zend_throw_error(NULL, "Wrong parameters for %s([string $message [, long $code [, Throwable $previous = NULL]]])", ZSTR_VAL(ce->name));
  260. return;
  261. }
  262. if (message) {
  263. ZVAL_STR(&tmp, message);
  264. zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
  265. }
  266. if (code) {
  267. ZVAL_LONG(&tmp, code);
  268. zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_CODE), &tmp);
  269. }
  270. if (previous) {
  271. zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_PREVIOUS), previous);
  272. }
  273. }
  274. /* }}} */
  275. /* {{{ proto Exception::__wakeup()
  276. Exception unserialize checks */
  277. #define CHECK_EXC_TYPE(id, type) \
  278. pvalue = zend_read_property_ex(i_get_exception_base(object), (object), ZSTR_KNOWN(id), 1, &value); \
  279. if (Z_TYPE_P(pvalue) != IS_NULL && Z_TYPE_P(pvalue) != type) { \
  280. zend_unset_property(i_get_exception_base(object), object, ZSTR_VAL(ZSTR_KNOWN(id)), ZSTR_LEN(ZSTR_KNOWN(id))); \
  281. }
  282. ZEND_METHOD(exception, __wakeup)
  283. {
  284. zval value, *pvalue;
  285. zval *object = getThis();
  286. CHECK_EXC_TYPE(ZEND_STR_MESSAGE, IS_STRING);
  287. CHECK_EXC_TYPE(ZEND_STR_STRING, IS_STRING);
  288. CHECK_EXC_TYPE(ZEND_STR_CODE, IS_LONG);
  289. CHECK_EXC_TYPE(ZEND_STR_FILE, IS_STRING);
  290. CHECK_EXC_TYPE(ZEND_STR_LINE, IS_LONG);
  291. CHECK_EXC_TYPE(ZEND_STR_TRACE, IS_ARRAY);
  292. pvalue = zend_read_property(i_get_exception_base(object), object, "previous", sizeof("previous")-1, 1, &value);
  293. if (pvalue && Z_TYPE_P(pvalue) != IS_NULL && (Z_TYPE_P(pvalue) != IS_OBJECT ||
  294. !instanceof_function(Z_OBJCE_P(pvalue), zend_ce_throwable) ||
  295. pvalue == object)) {
  296. zend_unset_property(i_get_exception_base(object), object, "previous", sizeof("previous")-1);
  297. }
  298. }
  299. /* }}} */
  300. /* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Throwable previous]]])
  301. ErrorException constructor */
  302. ZEND_METHOD(error_exception, __construct)
  303. {
  304. zend_string *message = NULL, *filename = NULL;
  305. zend_long code = 0, severity = E_ERROR, lineno;
  306. zval tmp, *object, *previous = NULL;
  307. int argc = ZEND_NUM_ARGS();
  308. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SllSlO!", &message, &code, &severity, &filename, &lineno, &previous, zend_ce_throwable) == FAILURE) {
  309. zend_class_entry *ce;
  310. if (Z_TYPE(EX(This)) == IS_OBJECT) {
  311. ce = Z_OBJCE(EX(This));
  312. } else if (Z_CE(EX(This))) {
  313. ce = Z_CE(EX(This));
  314. } else {
  315. ce = zend_ce_error_exception;
  316. }
  317. zend_throw_error(NULL, "Wrong parameters for %s([string $message [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Throwable $previous = NULL]]]]]])", ZSTR_VAL(ce->name));
  318. return;
  319. }
  320. object = getThis();
  321. if (message) {
  322. ZVAL_STR_COPY(&tmp, message);
  323. zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
  324. zval_ptr_dtor(&tmp);
  325. }
  326. if (code) {
  327. ZVAL_LONG(&tmp, code);
  328. zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_CODE), &tmp);
  329. }
  330. if (previous) {
  331. zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_PREVIOUS), previous);
  332. }
  333. ZVAL_LONG(&tmp, severity);
  334. zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_SEVERITY), &tmp);
  335. if (argc >= 4) {
  336. ZVAL_STR_COPY(&tmp, filename);
  337. zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
  338. zval_ptr_dtor(&tmp);
  339. if (argc < 5) {
  340. lineno = 0; /* invalidate lineno */
  341. }
  342. ZVAL_LONG(&tmp, lineno);
  343. zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
  344. }
  345. }
  346. /* }}} */
  347. #define DEFAULT_0_PARAMS \
  348. if (zend_parse_parameters_none() == FAILURE) { \
  349. return; \
  350. }
  351. #define GET_PROPERTY(object, id) \
  352. zend_read_property_ex(i_get_exception_base(object), (object), ZSTR_KNOWN(id), 0, &rv)
  353. #define GET_PROPERTY_SILENT(object, id) \
  354. zend_read_property_ex(i_get_exception_base(object), (object), ZSTR_KNOWN(id), 1, &rv)
  355. /* {{{ proto string Exception|Error::getFile()
  356. Get the file in which the exception occurred */
  357. ZEND_METHOD(exception, getFile)
  358. {
  359. zval *prop, rv;
  360. DEFAULT_0_PARAMS;
  361. prop = GET_PROPERTY(getThis(), ZEND_STR_FILE);
  362. ZVAL_DEREF(prop);
  363. ZVAL_COPY(return_value, prop);
  364. }
  365. /* }}} */
  366. /* {{{ proto int Exception|Error::getLine()
  367. Get the line in which the exception occurred */
  368. ZEND_METHOD(exception, getLine)
  369. {
  370. zval *prop, rv;
  371. DEFAULT_0_PARAMS;
  372. prop = GET_PROPERTY(getThis(), ZEND_STR_LINE);
  373. ZVAL_DEREF(prop);
  374. ZVAL_COPY(return_value, prop);
  375. }
  376. /* }}} */
  377. /* {{{ proto string Exception|Error::getMessage()
  378. Get the exception message */
  379. ZEND_METHOD(exception, getMessage)
  380. {
  381. zval *prop, rv;
  382. DEFAULT_0_PARAMS;
  383. prop = GET_PROPERTY(getThis(), ZEND_STR_MESSAGE);
  384. ZVAL_DEREF(prop);
  385. ZVAL_COPY(return_value, prop);
  386. }
  387. /* }}} */
  388. /* {{{ proto int Exception|Error::getCode()
  389. Get the exception code */
  390. ZEND_METHOD(exception, getCode)
  391. {
  392. zval *prop, rv;
  393. DEFAULT_0_PARAMS;
  394. prop = GET_PROPERTY(getThis(), ZEND_STR_CODE);
  395. ZVAL_DEREF(prop);
  396. ZVAL_COPY(return_value, prop);
  397. }
  398. /* }}} */
  399. /* {{{ proto array Exception|Error::getTrace()
  400. Get the stack trace for the location in which the exception occurred */
  401. ZEND_METHOD(exception, getTrace)
  402. {
  403. zval *prop, rv;
  404. DEFAULT_0_PARAMS;
  405. prop = GET_PROPERTY(getThis(), ZEND_STR_TRACE);
  406. ZVAL_DEREF(prop);
  407. ZVAL_COPY(return_value, prop);
  408. }
  409. /* }}} */
  410. /* {{{ proto int ErrorException::getSeverity()
  411. Get the exception severity */
  412. ZEND_METHOD(error_exception, getSeverity)
  413. {
  414. zval *prop, rv;
  415. DEFAULT_0_PARAMS;
  416. prop = GET_PROPERTY(getThis(), ZEND_STR_SEVERITY);
  417. ZVAL_DEREF(prop);
  418. ZVAL_COPY(return_value, prop);
  419. }
  420. /* }}} */
  421. #define TRACE_APPEND_KEY(key) do { \
  422. tmp = zend_hash_find(ht, key); \
  423. if (tmp) { \
  424. if (Z_TYPE_P(tmp) != IS_STRING) { \
  425. zend_error(E_WARNING, "Value for %s is no string", \
  426. ZSTR_VAL(key)); \
  427. smart_str_appends(str, "[unknown]"); \
  428. } else { \
  429. smart_str_appends(str, Z_STRVAL_P(tmp)); \
  430. } \
  431. } \
  432. } while (0)
  433. static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */
  434. {
  435. /* the trivial way would be to do
  436. * convert_to_string_ex(arg);
  437. * append it and kill the now tmp arg.
  438. * but that could cause some E_NOTICE and also damn long lines.
  439. */
  440. ZVAL_DEREF(arg);
  441. switch (Z_TYPE_P(arg)) {
  442. case IS_NULL:
  443. smart_str_appends(str, "NULL, ");
  444. break;
  445. case IS_STRING:
  446. smart_str_appendc(str, '\'');
  447. smart_str_append_escaped(str, Z_STRVAL_P(arg), MIN(Z_STRLEN_P(arg), 15));
  448. if (Z_STRLEN_P(arg) > 15) {
  449. smart_str_appends(str, "...', ");
  450. } else {
  451. smart_str_appends(str, "', ");
  452. }
  453. break;
  454. case IS_FALSE:
  455. smart_str_appends(str, "false, ");
  456. break;
  457. case IS_TRUE:
  458. smart_str_appends(str, "true, ");
  459. break;
  460. case IS_RESOURCE:
  461. smart_str_appends(str, "Resource id #");
  462. smart_str_append_long(str, Z_RES_HANDLE_P(arg));
  463. smart_str_appends(str, ", ");
  464. break;
  465. case IS_LONG:
  466. smart_str_append_long(str, Z_LVAL_P(arg));
  467. smart_str_appends(str, ", ");
  468. break;
  469. case IS_DOUBLE: {
  470. smart_str_append_printf(str, "%.*G", (int) EG(precision), Z_DVAL_P(arg));
  471. smart_str_appends(str, ", ");
  472. break;
  473. }
  474. case IS_ARRAY:
  475. smart_str_appends(str, "Array, ");
  476. break;
  477. case IS_OBJECT: {
  478. zend_string *class_name = Z_OBJ_HANDLER_P(arg, get_class_name)(Z_OBJ_P(arg));
  479. smart_str_appends(str, "Object(");
  480. smart_str_appends(str, ZSTR_VAL(class_name));
  481. smart_str_appends(str, "), ");
  482. zend_string_release_ex(class_name, 0);
  483. break;
  484. }
  485. }
  486. }
  487. /* }}} */
  488. static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /* {{{ */
  489. {
  490. zval *file, *tmp;
  491. smart_str_appendc(str, '#');
  492. smart_str_append_long(str, num);
  493. smart_str_appendc(str, ' ');
  494. file = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_FILE), 1);
  495. if (file) {
  496. if (Z_TYPE_P(file) != IS_STRING) {
  497. zend_error(E_WARNING, "Function name is no string");
  498. smart_str_appends(str, "[unknown function]");
  499. } else{
  500. zend_long line;
  501. tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_LINE), 1);
  502. if (tmp) {
  503. if (Z_TYPE_P(tmp) == IS_LONG) {
  504. line = Z_LVAL_P(tmp);
  505. } else {
  506. zend_error(E_WARNING, "Line is no long");
  507. line = 0;
  508. }
  509. } else {
  510. line = 0;
  511. }
  512. smart_str_append(str, Z_STR_P(file));
  513. smart_str_appendc(str, '(');
  514. smart_str_append_long(str, line);
  515. smart_str_appends(str, "): ");
  516. }
  517. } else {
  518. smart_str_appends(str, "[internal function]: ");
  519. }
  520. TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_CLASS));
  521. TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_TYPE));
  522. TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_FUNCTION));
  523. smart_str_appendc(str, '(');
  524. tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_ARGS), 1);
  525. if (tmp) {
  526. if (Z_TYPE_P(tmp) == IS_ARRAY) {
  527. size_t last_len = ZSTR_LEN(str->s);
  528. zval *arg;
  529. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmp), arg) {
  530. _build_trace_args(arg, str);
  531. } ZEND_HASH_FOREACH_END();
  532. if (last_len != ZSTR_LEN(str->s)) {
  533. ZSTR_LEN(str->s) -= 2; /* remove last ', ' */
  534. }
  535. } else {
  536. zend_error(E_WARNING, "args element is no array");
  537. }
  538. }
  539. smart_str_appends(str, ")\n");
  540. }
  541. /* }}} */
  542. /* {{{ proto string Exception|Error::getTraceAsString()
  543. Obtain the backtrace for the exception as a string (instead of an array) */
  544. ZEND_METHOD(exception, getTraceAsString)
  545. {
  546. zval *trace, *frame, rv;
  547. zend_ulong index;
  548. zval *object;
  549. zend_class_entry *base_ce;
  550. smart_str str = {0};
  551. uint32_t num = 0;
  552. DEFAULT_0_PARAMS;
  553. object = getThis();
  554. base_ce = i_get_exception_base(object);
  555. trace = zend_read_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_TRACE), 1, &rv);
  556. if (Z_TYPE_P(trace) != IS_ARRAY) {
  557. RETURN_FALSE;
  558. }
  559. ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) {
  560. if (Z_TYPE_P(frame) != IS_ARRAY) {
  561. zend_error(E_WARNING, "Expected array for frame " ZEND_ULONG_FMT, index);
  562. continue;
  563. }
  564. _build_trace_string(&str, Z_ARRVAL_P(frame), num++);
  565. } ZEND_HASH_FOREACH_END();
  566. smart_str_appendc(&str, '#');
  567. smart_str_append_long(&str, num);
  568. smart_str_appends(&str, " {main}");
  569. smart_str_0(&str);
  570. RETURN_NEW_STR(str.s);
  571. }
  572. /* }}} */
  573. /* {{{ proto Throwable Exception|Error::getPrevious()
  574. Return previous Throwable or NULL. */
  575. ZEND_METHOD(exception, getPrevious)
  576. {
  577. zval rv;
  578. DEFAULT_0_PARAMS;
  579. ZVAL_COPY(return_value, GET_PROPERTY_SILENT(getThis(), ZEND_STR_PREVIOUS));
  580. } /* }}} */
  581. /* {{{ proto string Exception|Error::__toString()
  582. Obtain the string representation of the Exception object */
  583. ZEND_METHOD(exception, __toString)
  584. {
  585. zval trace, *exception;
  586. zend_class_entry *base_ce;
  587. zend_string *str;
  588. zend_fcall_info fci;
  589. zval rv, tmp;
  590. zend_string *fname;
  591. DEFAULT_0_PARAMS;
  592. str = ZSTR_EMPTY_ALLOC();
  593. exception = getThis();
  594. fname = zend_string_init("gettraceasstring", sizeof("gettraceasstring")-1, 0);
  595. while (exception && Z_TYPE_P(exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception), zend_ce_throwable)) {
  596. zend_string *prev_str = str;
  597. zend_string *message = zval_get_string(GET_PROPERTY(exception, ZEND_STR_MESSAGE));
  598. zend_string *file = zval_get_string(GET_PROPERTY(exception, ZEND_STR_FILE));
  599. zend_long line = zval_get_long(GET_PROPERTY(exception, ZEND_STR_LINE));
  600. fci.size = sizeof(fci);
  601. ZVAL_STR(&fci.function_name, fname);
  602. fci.object = Z_OBJ_P(exception);
  603. fci.retval = &trace;
  604. fci.param_count = 0;
  605. fci.params = NULL;
  606. fci.no_separation = 1;
  607. zend_call_function(&fci, NULL);
  608. if (Z_TYPE(trace) != IS_STRING) {
  609. zval_ptr_dtor(&trace);
  610. ZVAL_UNDEF(&trace);
  611. }
  612. if ((Z_OBJCE_P(exception) == zend_ce_type_error || Z_OBJCE_P(exception) == zend_ce_argument_count_error) && strstr(ZSTR_VAL(message), ", called in ")) {
  613. zend_string *real_message = zend_strpprintf(0, "%s and defined", ZSTR_VAL(message));
  614. zend_string_release_ex(message, 0);
  615. message = real_message;
  616. }
  617. if (ZSTR_LEN(message) > 0) {
  618. str = zend_strpprintf(0, "%s: %s in %s:" ZEND_LONG_FMT
  619. "\nStack trace:\n%s%s%s",
  620. ZSTR_VAL(Z_OBJCE_P(exception)->name), ZSTR_VAL(message), ZSTR_VAL(file), line,
  621. (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
  622. ZSTR_LEN(prev_str) ? "\n\nNext " : "", ZSTR_VAL(prev_str));
  623. } else {
  624. str = zend_strpprintf(0, "%s in %s:" ZEND_LONG_FMT
  625. "\nStack trace:\n%s%s%s",
  626. ZSTR_VAL(Z_OBJCE_P(exception)->name), ZSTR_VAL(file), line,
  627. (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
  628. ZSTR_LEN(prev_str) ? "\n\nNext " : "", ZSTR_VAL(prev_str));
  629. }
  630. zend_string_release_ex(prev_str, 0);
  631. zend_string_release_ex(message, 0);
  632. zend_string_release_ex(file, 0);
  633. zval_ptr_dtor(&trace);
  634. Z_PROTECT_RECURSION_P(exception);
  635. exception = GET_PROPERTY(exception, ZEND_STR_PREVIOUS);
  636. if (exception && Z_TYPE_P(exception) == IS_OBJECT && Z_IS_RECURSIVE_P(exception)) {
  637. break;
  638. }
  639. }
  640. zend_string_release_ex(fname, 0);
  641. exception = getThis();
  642. /* Reset apply counts */
  643. while (exception && Z_TYPE_P(exception) == IS_OBJECT && (base_ce = i_get_exception_base(exception)) && instanceof_function(Z_OBJCE_P(exception), base_ce)) {
  644. if (Z_IS_RECURSIVE_P(exception)) {
  645. Z_UNPROTECT_RECURSION_P(exception);
  646. } else {
  647. break;
  648. }
  649. exception = GET_PROPERTY(exception, ZEND_STR_PREVIOUS);
  650. }
  651. exception = getThis();
  652. base_ce = i_get_exception_base(exception);
  653. /* We store the result in the private property string so we can access
  654. * the result in uncaught exception handlers without memleaks. */
  655. ZVAL_STR(&tmp, str);
  656. zend_update_property_ex(base_ce, exception, ZSTR_KNOWN(ZEND_STR_STRING), &tmp);
  657. RETURN_STR(str);
  658. }
  659. /* }}} */
  660. /** {{{ Throwable method definition */
  661. static const zend_function_entry zend_funcs_throwable[] = {
  662. ZEND_ABSTRACT_ME(throwable, getMessage, NULL)
  663. ZEND_ABSTRACT_ME(throwable, getCode, NULL)
  664. ZEND_ABSTRACT_ME(throwable, getFile, NULL)
  665. ZEND_ABSTRACT_ME(throwable, getLine, NULL)
  666. ZEND_ABSTRACT_ME(throwable, getTrace, NULL)
  667. ZEND_ABSTRACT_ME(throwable, getPrevious, NULL)
  668. ZEND_ABSTRACT_ME(throwable, getTraceAsString, NULL)
  669. ZEND_ABSTRACT_ME(throwable, __toString, NULL)
  670. ZEND_FE_END
  671. };
  672. /* }}} */
  673. /* {{{ internal structs */
  674. /* All functions that may be used in uncaught exception handlers must be final
  675. * and must not throw exceptions. Otherwise we would need a facility to handle
  676. * such exceptions in that handler.
  677. * Also all getXY() methods are final because thy serve as read only access to
  678. * their corresponding properties, no more, no less. If after all you need to
  679. * override somthing then it is method __toString().
  680. * And never try to change the state of exceptions and never implement anything
  681. * that gives the user anything to accomplish this.
  682. */
  683. ZEND_BEGIN_ARG_INFO_EX(arginfo_exception___construct, 0, 0, 0)
  684. ZEND_ARG_INFO(0, message)
  685. ZEND_ARG_INFO(0, code)
  686. ZEND_ARG_INFO(0, previous)
  687. ZEND_END_ARG_INFO()
  688. static const zend_function_entry default_exception_functions[] = {
  689. ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
  690. ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC)
  691. ZEND_ME(exception, __wakeup, NULL, ZEND_ACC_PUBLIC)
  692. ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
  693. ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
  694. ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
  695. ZEND_ME(exception, getLine, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
  696. ZEND_ME(exception, getTrace, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
  697. ZEND_ME(exception, getPrevious, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
  698. ZEND_ME(exception, getTraceAsString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
  699. ZEND_ME(exception, __toString, NULL, 0)
  700. ZEND_FE_END
  701. };
  702. ZEND_BEGIN_ARG_INFO_EX(arginfo_error_exception___construct, 0, 0, 0)
  703. ZEND_ARG_INFO(0, message)
  704. ZEND_ARG_INFO(0, code)
  705. ZEND_ARG_INFO(0, severity)
  706. ZEND_ARG_INFO(0, filename)
  707. ZEND_ARG_INFO(0, lineno)
  708. ZEND_ARG_INFO(0, previous)
  709. ZEND_END_ARG_INFO()
  710. static const zend_function_entry error_exception_functions[] = {
  711. ZEND_ME(error_exception, __construct, arginfo_error_exception___construct, ZEND_ACC_PUBLIC)
  712. ZEND_ME(error_exception, getSeverity, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
  713. ZEND_FE_END
  714. };
  715. /* }}} */
  716. void zend_register_default_exception(void) /* {{{ */
  717. {
  718. zend_class_entry ce;
  719. REGISTER_MAGIC_INTERFACE(throwable, Throwable);
  720. memcpy(&default_exception_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  721. default_exception_handlers.clone_obj = NULL;
  722. INIT_CLASS_ENTRY(ce, "Exception", default_exception_functions);
  723. zend_ce_exception = zend_register_internal_class_ex(&ce, NULL);
  724. zend_ce_exception->create_object = zend_default_exception_new;
  725. zend_class_implements(zend_ce_exception, 1, zend_ce_throwable);
  726. zend_declare_property_string(zend_ce_exception, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED);
  727. zend_declare_property_string(zend_ce_exception, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE);
  728. zend_declare_property_long(zend_ce_exception, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED);
  729. zend_declare_property_null(zend_ce_exception, "file", sizeof("file")-1, ZEND_ACC_PROTECTED);
  730. zend_declare_property_null(zend_ce_exception, "line", sizeof("line")-1, ZEND_ACC_PROTECTED);
  731. zend_declare_property_null(zend_ce_exception, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE);
  732. zend_declare_property_null(zend_ce_exception, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE);
  733. INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions);
  734. zend_ce_error_exception = zend_register_internal_class_ex(&ce, zend_ce_exception);
  735. zend_ce_error_exception->create_object = zend_error_exception_new;
  736. zend_declare_property_long(zend_ce_error_exception, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED);
  737. INIT_CLASS_ENTRY(ce, "Error", default_exception_functions);
  738. zend_ce_error = zend_register_internal_class_ex(&ce, NULL);
  739. zend_ce_error->create_object = zend_default_exception_new;
  740. zend_class_implements(zend_ce_error, 1, zend_ce_throwable);
  741. zend_declare_property_string(zend_ce_error, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED);
  742. zend_declare_property_string(zend_ce_error, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE);
  743. zend_declare_property_long(zend_ce_error, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED);
  744. zend_declare_property_null(zend_ce_error, "file", sizeof("file")-1, ZEND_ACC_PROTECTED);
  745. zend_declare_property_null(zend_ce_error, "line", sizeof("line")-1, ZEND_ACC_PROTECTED);
  746. zend_declare_property_null(zend_ce_error, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE);
  747. zend_declare_property_null(zend_ce_error, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE);
  748. INIT_CLASS_ENTRY(ce, "CompileError", NULL);
  749. zend_ce_compile_error = zend_register_internal_class_ex(&ce, zend_ce_error);
  750. zend_ce_compile_error->create_object = zend_default_exception_new;
  751. INIT_CLASS_ENTRY(ce, "ParseError", NULL);
  752. zend_ce_parse_error = zend_register_internal_class_ex(&ce, zend_ce_compile_error);
  753. zend_ce_parse_error->create_object = zend_default_exception_new;
  754. INIT_CLASS_ENTRY(ce, "TypeError", NULL);
  755. zend_ce_type_error = zend_register_internal_class_ex(&ce, zend_ce_error);
  756. zend_ce_type_error->create_object = zend_default_exception_new;
  757. INIT_CLASS_ENTRY(ce, "ArgumentCountError", NULL);
  758. zend_ce_argument_count_error = zend_register_internal_class_ex(&ce, zend_ce_type_error);
  759. zend_ce_argument_count_error->create_object = zend_default_exception_new;
  760. INIT_CLASS_ENTRY(ce, "ArithmeticError", NULL);
  761. zend_ce_arithmetic_error = zend_register_internal_class_ex(&ce, zend_ce_error);
  762. zend_ce_arithmetic_error->create_object = zend_default_exception_new;
  763. INIT_CLASS_ENTRY(ce, "DivisionByZeroError", NULL);
  764. zend_ce_division_by_zero_error = zend_register_internal_class_ex(&ce, zend_ce_arithmetic_error);
  765. zend_ce_division_by_zero_error->create_object = zend_default_exception_new;
  766. }
  767. /* }}} */
  768. /* {{{ Deprecated - Use zend_ce_exception directly instead */
  769. ZEND_API zend_class_entry *zend_exception_get_default(void)
  770. {
  771. return zend_ce_exception;
  772. }
  773. /* }}} */
  774. /* {{{ Deprecated - Use zend_ce_error_exception directly instead */
  775. ZEND_API zend_class_entry *zend_get_error_exception(void)
  776. {
  777. return zend_ce_error_exception;
  778. }
  779. /* }}} */
  780. ZEND_API ZEND_COLD zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code) /* {{{ */
  781. {
  782. zval ex, tmp;
  783. if (exception_ce) {
  784. if (!instanceof_function(exception_ce, zend_ce_throwable)) {
  785. zend_error(E_NOTICE, "Exceptions must implement Throwable");
  786. exception_ce = zend_ce_exception;
  787. }
  788. } else {
  789. exception_ce = zend_ce_exception;
  790. }
  791. object_init_ex(&ex, exception_ce);
  792. if (message) {
  793. ZVAL_STRING(&tmp, message);
  794. zend_update_property_ex(exception_ce, &ex, ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
  795. zval_ptr_dtor(&tmp);
  796. }
  797. if (code) {
  798. ZVAL_LONG(&tmp, code);
  799. zend_update_property_ex(exception_ce, &ex, ZSTR_KNOWN(ZEND_STR_CODE), &tmp);
  800. }
  801. zend_throw_exception_internal(&ex);
  802. return Z_OBJ(ex);
  803. }
  804. /* }}} */
  805. ZEND_API ZEND_COLD zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format, ...) /* {{{ */
  806. {
  807. va_list arg;
  808. char *message;
  809. zend_object *obj;
  810. va_start(arg, format);
  811. zend_vspprintf(&message, 0, format, arg);
  812. va_end(arg);
  813. obj = zend_throw_exception(exception_ce, message, code);
  814. efree(message);
  815. return obj;
  816. }
  817. /* }}} */
  818. ZEND_API ZEND_COLD zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, zend_long code, int severity) /* {{{ */
  819. {
  820. zval ex, tmp;
  821. zend_object *obj = zend_throw_exception(exception_ce, message, code);
  822. ZVAL_OBJ(&ex, obj);
  823. ZVAL_LONG(&tmp, severity);
  824. zend_update_property_ex(zend_ce_error_exception, &ex, ZSTR_KNOWN(ZEND_STR_SEVERITY), &tmp);
  825. return obj;
  826. }
  827. /* }}} */
  828. static void zend_error_va(int type, const char *file, uint32_t lineno, const char *format, ...) /* {{{ */
  829. {
  830. va_list args;
  831. va_start(args, format);
  832. zend_error_cb(type, file, lineno, format, args);
  833. va_end(args);
  834. }
  835. /* }}} */
  836. static void zend_error_helper(int type, const char *filename, const uint32_t lineno, const char *format, ...) /* {{{ */
  837. {
  838. va_list va;
  839. va_start(va, format);
  840. zend_error_cb(type, filename, lineno, format, va);
  841. va_end(va);
  842. }
  843. /* }}} */
  844. /* This function doesn't return if it uses E_ERROR */
  845. ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* {{{ */
  846. {
  847. zval exception, rv;
  848. zend_class_entry *ce_exception;
  849. ZVAL_OBJ(&exception, ex);
  850. ce_exception = Z_OBJCE(exception);
  851. EG(exception) = NULL;
  852. if (ce_exception == zend_ce_parse_error || ce_exception == zend_ce_compile_error) {
  853. zend_string *message = zval_get_string(GET_PROPERTY(&exception, ZEND_STR_MESSAGE));
  854. zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
  855. zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));
  856. zend_error_helper(ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR,
  857. ZSTR_VAL(file), line, "%s", ZSTR_VAL(message));
  858. zend_string_release_ex(file, 0);
  859. zend_string_release_ex(message, 0);
  860. } else if (instanceof_function(ce_exception, zend_ce_throwable)) {
  861. zval tmp, rv;
  862. zend_string *str, *file = NULL;
  863. zend_long line = 0;
  864. zend_call_method_with_0_params(&exception, ce_exception, &ex->ce->__tostring, "__tostring", &tmp);
  865. if (!EG(exception)) {
  866. if (Z_TYPE(tmp) != IS_STRING) {
  867. zend_error(E_WARNING, "%s::__toString() must return a string", ZSTR_VAL(ce_exception->name));
  868. } else {
  869. zend_update_property_ex(i_get_exception_base(&exception), &exception, ZSTR_KNOWN(ZEND_STR_STRING), &tmp);
  870. }
  871. }
  872. zval_ptr_dtor(&tmp);
  873. if (EG(exception)) {
  874. zval zv;
  875. ZVAL_OBJ(&zv, EG(exception));
  876. /* do the best we can to inform about the inner exception */
  877. if (instanceof_function(ce_exception, zend_ce_exception) || instanceof_function(ce_exception, zend_ce_error)) {
  878. file = zval_get_string(GET_PROPERTY_SILENT(&zv, ZEND_STR_FILE));
  879. line = zval_get_long(GET_PROPERTY_SILENT(&zv, ZEND_STR_LINE));
  880. }
  881. zend_error_va(E_WARNING, (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line,
  882. "Uncaught %s in exception handling during call to %s::__tostring()",
  883. ZSTR_VAL(Z_OBJCE(zv)->name), ZSTR_VAL(ce_exception->name));
  884. if (file) {
  885. zend_string_release_ex(file, 0);
  886. }
  887. }
  888. str = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_STRING));
  889. file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
  890. line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));
  891. zend_error_va(severity, (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line,
  892. "Uncaught %s\n thrown", ZSTR_VAL(str));
  893. zend_string_release_ex(str, 0);
  894. zend_string_release_ex(file, 0);
  895. } else {
  896. zend_error(severity, "Uncaught exception '%s'", ZSTR_VAL(ce_exception->name));
  897. }
  898. OBJ_RELEASE(ex);
  899. }
  900. /* }}} */
  901. ZEND_API ZEND_COLD void zend_throw_exception_object(zval *exception) /* {{{ */
  902. {
  903. zend_class_entry *exception_ce;
  904. if (exception == NULL || Z_TYPE_P(exception) != IS_OBJECT) {
  905. zend_error_noreturn(E_CORE_ERROR, "Need to supply an object when throwing an exception");
  906. }
  907. exception_ce = Z_OBJCE_P(exception);
  908. if (!exception_ce || !instanceof_function(exception_ce, zend_ce_throwable)) {
  909. zend_throw_error(NULL, "Cannot throw objects that do not implement Throwable");
  910. zval_ptr_dtor(exception);
  911. return;
  912. }
  913. zend_throw_exception_internal(exception);
  914. }
  915. /* }}} */
  916. /*
  917. * Local variables:
  918. * tab-width: 4
  919. * c-basic-offset: 4
  920. * indent-tabs-mode: t
  921. * End:
  922. * vim600: sw=4 ts=4 fdm=marker
  923. * vim<600: sw=4 ts=4
  924. */