Fwd: Re: Buffer Overflow with all versions of Internet Explorer and Javacript.
Koos Vriezen
koos.vriezen at xs4all.nl
Sun Aug 4 22:09:41 BST 2002
On Wed, 5 Jun 2002, Koos Vriezen wrote:
> On Wed, 5 Jun 2002, Harri Porten wrote:
> > On Tue, 4 Jun 2002, Koos Vriezen wrote:
> > > On Tue, 4 Jun 2002, Koos Vriezen wrote:
> > > > On Tue, 4 Jun 2002, Harri Porten wrote:
> > > > > But I wouldn't know what to
> > > > > really do against infinite loops like while(1);. They can be by design and
> > > > > harmless but there is no way to abort them, yet. Easier with threading.
> > > >
> > > > Maybe use SIGALARM?
> > >
> > > Just a small hack that stops a 'while(true);' script after 5 seconds:
> >
> > SIGALARM is also the best solution I can think of. But it needs more
> > thinking as it has to be made more flexible. If the interpreter hangs in
> > a call to an interactive function (e.g. window.alert()) it's perfectly
> > acceptable to wait infinitely.
>
>
> Hmmm, just looked at the setitimer manpage. ITIMER_VIRTUAL seems a good
> option. It doesn't decrement with 'window.alert' alikes. We also get
> milli seconds resolution. Eg.
> signal(SIGVTALRM, alarmHandler);
> struct itimerval tv = { { 2, 0}, { 5, 0 } };
> setitimer(ITIMER_VIRTUAL, &tv, 0L);
> Completion comp = m_script->evaluate(code, thisNode);
> struct itimerval tv2 = { { 0, 0}, { 0, 0 } };
> setitimer(ITIMER_VIRTUAL, &tv2, 0L);
>
> seems to work. (Strange, without a interval value, the signal is not
> delivered.) However, this wouldn't fix the infinitely case ;)
Still had this small hack in my tree. Didn't see any problems with it,
so I de-hacked it a little. The attached patch does:
- prevents JS to hang khtml with scripts like 'while(1);',
- asks the user if a script should be terminated after it uses more than a
predefined time (here 5 seconds), and repeats this question after
another predefined time (here 2 seconds),
- it only measures CPU time consumed by khtml, so wait for user input or
Java calls, can't trigger this alarm.
Changing a static bool in KJS::ExecState from a signal handler, is
pretty save imho.
Regards,
Koos Vriezen
-------------- next part --------------
Index: kjs/interpreter.cpp
===================================================================
RCS file: /home/kde/kdelibs/kjs/interpreter.cpp,v
retrieving revision 1.11
diff -u -3 -p -r1.11 interpreter.cpp
--- kjs/interpreter.cpp 2002/06/25 19:13:58 1.11
+++ kjs/interpreter.cpp 2002/08/04 20:48:21
@@ -355,6 +355,7 @@ void ExecState::setException(const Value
void ExecState::clearException()
{
+ terminate_request = false;
rep->exception = Value();
}
@@ -363,8 +364,12 @@ Value ExecState::exception() const
return rep->exception;
}
+bool ExecState::terminate_request = false;
+
bool ExecState::hadException() const
{
+ if (terminate_request)
+ rep->exception = Error::create((ExecState*)this);
return !rep->exception.isNull();
}
Index: kjs/interpreter.h
===================================================================
RCS file: /home/kde/kdelibs/kjs/interpreter.h,v
retrieving revision 1.10
diff -u -3 -p -r1.10 interpreter.h
--- kjs/interpreter.h 2002/06/19 08:21:00 1.10
+++ kjs/interpreter.h 2002/08/04 20:48:21
@@ -390,9 +390,14 @@ namespace KJS {
Value exception() const;
bool hadException() const;
+ /*
+ * request for ending execution with an exception
+ */
+ static void requestTerminate() { terminate_request = true; }
private:
ExecState(Interpreter *interp, ContextImp *con);
ExecStateImp *rep;
+ static bool terminate_request;
};
}; // namespace
Index: khtml/ecma/kjs_proxy.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/ecma/kjs_proxy.cpp,v
retrieving revision 1.80
diff -u -3 -p -r1.80 kjs_proxy.cpp
--- khtml/ecma/kjs_proxy.cpp 2002/07/28 01:20:32 1.80
+++ khtml/ecma/kjs_proxy.cpp 2002/08/04 20:48:41
@@ -27,6 +27,11 @@
#include <khtml_part.h>
#include <kprotocolmanager.h>
#include <kdebug.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
#include <kjs/collector.h>
#include <assert.h>
@@ -55,6 +60,11 @@ public:
void applyUserAgent();
private:
+ static void alarmHandler(int) {
+ kdDebug(6070) << "alarmhandler" << endl;
+ if (KMessageBox::warningYesNo(0L, i18n("A script takes a lot of time.\nTerminate it?"), "JavaScript", i18n("OK"), i18n("Cancel")) == KMessageBox::Yes)
+ ExecState::requestTerminate();
+ }
KJS::ScriptInterpreter* m_script;
bool m_debugEnabled;
#ifndef NDEBUG
@@ -134,7 +144,16 @@ QVariant KJSProxyImpl::evaluate(QString
KJS::Value thisNode = n.isNull() ? Window::retrieve( m_part ) : getDOMNode(m_script->globalExec(),n);
UString code( str );
+
+ void (*oldAlarmHandler)(int) = signal(SIGVTALRM, KJSProxyImpl::alarmHandler);
+ itimerval oldtv, tv = { { 2, 0 }, { 5, 0 } };
+ setitimer(ITIMER_VIRTUAL, &tv, &oldtv);
+
Completion comp = m_script->evaluate(code, thisNode);
+
+ setitimer(ITIMER_VIRTUAL, &oldtv, 0L);
+ signal(SIGVTALRM, oldAlarmHandler);
+
bool success = ( comp.complType() == Normal ) || ( comp.complType() == ReturnValue );
#ifdef KJS_DEBUGGER
More information about the kfm-devel
mailing list