From a3b1dc680aa7947c5ae0613c9446b7d1b4825e2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Mon, 27 Sep 2010 19:06:30 +0200
Subject: [PATCH] Unlink ONERROR's before calling them to avoid recursion on
 error.

Fixes LysLysKOM 18719549/Pike mailinglist 12047.
Thanks to Artur Skawina <art.08.09@gmail.com> for the report.

Rev: src/error.c:1.170
Rev: src/pike_error.h:1.56
Rev: src/testsuite.in:1.899
---
 src/error.c      | 17 ++++++++++-------
 src/pike_error.h |  4 ++--
 src/testsuite.in |  9 ++++++++-
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/src/error.c b/src/error.c
index 3a9c7f66a1..3a91532862 100644
--- a/src/error.c
+++ b/src/error.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: error.c,v 1.169 2010/02/21 22:42:19 srb Exp $
+|| $Id: error.c,v 1.170 2010/09/27 17:06:17 grubba Exp $
 */
 
 #define NO_PIKE_SHORTHAND
@@ -135,7 +135,8 @@ PMOD_EXPORT DECLSPEC(noreturn) void pike_throw(void) ATTRIBUTE((noreturn))
   {
     while(Pike_interpreter.recoveries->onerror)
     {
-      while(Pike_fp != Pike_interpreter.recoveries->onerror->frame_pointer)
+      ONERROR *err = Pike_interpreter.recoveries->onerror;
+      while(Pike_fp != err->frame_pointer)
       {
 #ifdef PIKE_DEBUG
 	if(!Pike_fp)
@@ -144,8 +145,8 @@ PMOD_EXPORT DECLSPEC(noreturn) void pike_throw(void) ATTRIBUTE((noreturn))
 	POP_PIKE_FRAME();
       }
 
-      (*Pike_interpreter.recoveries->onerror->func)(Pike_interpreter.recoveries->onerror->arg);
-      Pike_interpreter.recoveries->onerror=Pike_interpreter.recoveries->onerror->previous;
+      Pike_interpreter.recoveries->onerror = err->previous;
+      (*err->func)(err->arg);
     }
 
     {
@@ -170,7 +171,9 @@ PMOD_EXPORT DECLSPEC(noreturn) void pike_throw(void) ATTRIBUTE((noreturn))
 
   while(Pike_interpreter.recoveries->onerror)
   {
-    while(Pike_fp != Pike_interpreter.recoveries->onerror->frame_pointer)
+    ONERROR *err = Pike_interpreter.recoveries->onerror;
+
+    while(Pike_fp != err->frame_pointer)
     {
 #ifdef PIKE_DEBUG
       if(!Pike_fp)
@@ -178,8 +181,8 @@ PMOD_EXPORT DECLSPEC(noreturn) void pike_throw(void) ATTRIBUTE((noreturn))
 #endif
       POP_PIKE_FRAME();
     }
-    (*Pike_interpreter.recoveries->onerror->func)(Pike_interpreter.recoveries->onerror->arg);
-    Pike_interpreter.recoveries->onerror=Pike_interpreter.recoveries->onerror->previous;
+    Pike_interpreter.recoveries->onerror = err->previous;
+    (*err->func)(err->arg);
   }
 
   while(Pike_fp != Pike_interpreter.recoveries->frame_pointer)
diff --git a/src/pike_error.h b/src/pike_error.h
index 7924b65072..570981da92 100644
--- a/src/pike_error.h
+++ b/src/pike_error.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: pike_error.h,v 1.55 2010/02/19 10:15:49 srb Exp $
+|| $Id: pike_error.h,v 1.56 2010/09/27 17:05:57 grubba Exp $
 */
 
 #ifndef PIKE_ERROR_H
@@ -231,8 +231,8 @@ PMOD_EXPORT extern const char msg_assert_onerr[];
 #endif /* PIKE_DEBUG */
 
 #define CALL_AND_UNSET_ONERROR(X) do {		\
-     X.func(X.arg);				\
      UNSET_ONERROR(X);				\
+     X.func(X.arg);				\
   }while(0)
 
 #if defined(PIKE_DEBUG) && 0
diff --git a/src/testsuite.in b/src/testsuite.in
index 2457a8820f..ae07a9d370 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,5 +1,5 @@
 START_MARKER
-test_true([["$Id: testsuite.in,v 1.898 2010/07/27 15:33:35 mast Exp $"]]);
+test_true([["$Id: testsuite.in,v 1.899 2010/09/27 17:06:30 grubba Exp $"]]);
 
 // This triggered a bug only if run sufficiently early.
 test_compile_any([[#pike 7.2]])
@@ -3952,6 +3952,13 @@ test_any([[
   return Y(5)->x;
 ]], 7)
 
+test_eval_error([[
+  // Triggered infinite recursion and core dump.
+  // cf LysLysKOM 18719518/Pike mailinglist 12047.
+  object o = class{}();
+  o->foo += "";
+]])
+
 test_compile_error([[
   class X {
     int x;
-- 
GitLab