From 6a8d493b8c0327fb4188d53d0b4a3cc2495f6999 Mon Sep 17 00:00:00 2001 From: rswindell <> Date: Mon, 11 Mar 2002 18:30:53 +0000 Subject: [PATCH] Added BranchCallback for detecting infinite loops and releasing timeslices. --- src/sbbs3/exec.cpp | 25 +++++++++++++++++++++++++ src/sbbs3/services.c | 43 +++++++++++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp index 1478cea8f3..aa99f66d30 100644 --- a/src/sbbs3/exec.cpp +++ b/src/sbbs3/exec.cpp @@ -524,6 +524,29 @@ char * sbbs_t::copystrvar(csi_t *csi, char *p, char *str) #ifdef JAVASCRIPT +static JSBool +js_BranchCallback(JSContext *cx, JSScript *script) +{ + sbbs_t* sbbs; + + if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL) + return(JS_FALSE); + + sbbs->js_loop++; + + /* Termination and infinite loop detection */ + if(sbbs->terminated || sbbs->js_loop>JAVASCRIPT_BRANCH_LIMIT) { + sbbs->js_loop=0; + return(JS_FALSE); + } + + /* Give up timeslices every once in a while */ + if(!(sbbs->js_loop%JAVASCRIPT_YIELD_FREQUENCY)) + mswait(1); + + return(JS_TRUE); +} + static JSClass js_scope_class ={ "Scope", 0, /* flags */ @@ -607,6 +630,8 @@ long sbbs_t::js_execfile(char *cmd) return(-1); } + JS_SetBranchCallback(js_cx, js_BranchCallback); + JS_ExecuteScript(js_cx, js_scope, js_script, &rval); JS_DestroyScript(js_cx, js_script); diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c index edde9fac5e..40008173e3 100644 --- a/src/sbbs3/services.c +++ b/src/sbbs3/services.c @@ -100,9 +100,10 @@ typedef struct { user_t user; client_t* client; service_t* service; + ulong js_loop; } service_client_t; -static service_t *service; //[MAX_SERVICES]; +static service_t *service; static DWORD services=0; static int lprintf(char *fmt, ...) @@ -487,20 +488,15 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client, jsval val; BOOL success=FALSE; -// lprintf("%04d JavaScript: Initializing context",sock); - if((js_cx = JS_NewContext(js_runtime, JAVASCRIPT_CONTEXT_STACK))==NULL) return(NULL); -// lprintf("%04d JavaScript: Context created",sock); - JS_SetErrorReporter(js_cx, js_ErrorReporter); do { JS_SetContextPrivate(js_cx, service_client); -// lprintf("%04d JavaScript: Initializing Global object",sock); if((js_glob=js_CreateGlobalObject(js_cx, &scfg))==NULL) break; @@ -527,7 +523,6 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client, if(js_CreateFileClass(js_cx, js_glob)==NULL) break; -// lprintf("%04d JavaScript: Initializing System object",sock); if(js_CreateSystemObject(js_cx, js_glob, &scfg, uptime)==NULL) break; @@ -561,6 +556,36 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client, return(js_cx); } +static JSBool +js_BranchCallback(JSContext *cx, JSScript *script) +{ + service_client_t* client; + + if((client=(service_client_t*)JS_GetContextPrivate(cx))==NULL) + return(JS_FALSE); + + client->js_loop++; + + /* Terminated? */ + if(terminated) { + lprintf("%04d %s !Terminated" + ,client->socket,client->service->protocol); + return(JS_FALSE); + } + /* Infinite loop detection */ + if(client->js_loop>JAVASCRIPT_BRANCH_LIMIT) { + lprintf("%04d %s !INFINITE LOOOP (%lu branches) detected" + ,client->socket,client->service->protocol,JAVASCRIPT_BRANCH_LIMIT); + client->js_loop=0; + return(JS_FALSE); + } + /* Give up timeslices every once in a while */ + if(!(client->js_loop%JAVASCRIPT_YIELD_FREQUENCY)) + mswait(1); + + return(JS_TRUE); +} + static void js_service_thread(void* arg) { @@ -710,14 +735,12 @@ static void js_service_thread(void* arg) if(js_script==NULL) lprintf("%04d !JavaScript FAILED to compile script (%s)",socket,spath); else { + JS_SetBranchCallback(js_cx, js_BranchCallback); JS_ExecuteScript(js_cx, js_glob, js_script, &rval); -// lprintf("%04d %s JS_DestroyScript",socket,service->protocol); JS_DestroyScript(js_cx, js_script); } -// lprintf("%04d %s JS_DestroyContext",socket,service->protocol); JS_DestroyContext(js_cx); /* Free Context */ -// lprintf("%04d %s JS_DestroyRuntime",socket,service->protocol); JS_DestroyRuntime(js_runtime); if(service_client.user.number) { -- GitLab