From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Andreas Schwab Newsgroups: gmane.emacs.bugs Subject: bug#31545: xwidget-webkit-execute-script does not protect script against GC Date: Mon, 21 May 2018 22:54:49 +0200 Message-ID: <87bmd8686e.fsf@igel.home> References: <8736yl19lu.fsf@igel.home> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: blaine.gmane.org 1526935990 2274 195.159.176.226 (21 May 2018 20:53:10 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 21 May 2018 20:53:10 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) To: 31545-done@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon May 21 22:53:06 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fKrnl-0000Vc-F9 for geb-bug-gnu-emacs@m.gmane.org; Mon, 21 May 2018 22:53:05 +0200 Original-Received: from localhost ([::1]:52416 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fKrpq-0001Qv-Ut for geb-bug-gnu-emacs@m.gmane.org; Mon, 21 May 2018 16:55:14 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:58762) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fKrph-0001Od-V8 for bug-gnu-emacs@gnu.org; Mon, 21 May 2018 16:55:07 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fKrpe-0003KK-Om for bug-gnu-emacs@gnu.org; Mon, 21 May 2018 16:55:06 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:35392) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fKrpe-0003Js-Lt for bug-gnu-emacs@gnu.org; Mon, 21 May 2018 16:55:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1fKrpe-0000pi-97 for bug-gnu-emacs@gnu.org; Mon, 21 May 2018 16:55:02 -0400 Resent-From: Andreas Schwab Original-Sender: "Debbugs-submit" Resent-To: bug-gnu-emacs@gnu.org Resent-Date: Mon, 21 May 2018 20:55:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: cc-closed 31545 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Mail-Followup-To: 31545@debbugs.gnu.org, schwab@linux-m68k.org, schwab@linux-m68k.org Original-Received: via spool by 31545-done@debbugs.gnu.org id=D31545.15269360953182 (code D ref 31545); Mon, 21 May 2018 20:55:02 +0000 Original-Received: (at 31545-done) by debbugs.gnu.org; 21 May 2018 20:54:55 +0000 Original-Received: from localhost ([127.0.0.1]:43289 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fKrpW-0000pG-MD for submit@debbugs.gnu.org; Mon, 21 May 2018 16:54:55 -0400 Original-Received: from mail-out.m-online.net ([212.18.0.10]:48308) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fKrpU-0000p7-Jo for 31545-done@debbugs.gnu.org; Mon, 21 May 2018 16:54:53 -0400 Original-Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 40qWHb4Pkcz1qvn4 for <31545-done@debbugs.gnu.org>; Mon, 21 May 2018 22:54:51 +0200 (CEST) Original-Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 40qWHb2bBkz1qqlF for <31545-done@debbugs.gnu.org>; Mon, 21 May 2018 22:54:51 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Original-Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id RCFJwi9y6Ua9 for <31545-done@debbugs.gnu.org>; Mon, 21 May 2018 22:54:50 +0200 (CEST) X-Auth-Info: AWeXHZi4MJlmzoHc3lS6EdkAdHuEAL8Ak+NPn1JnD37qmfXlgcZ/ntvZ1rvXPrX2 Original-Received: from localhost (ppp-188-174-150-148.dynamic.mnet-online.de [188.174.150.148]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA for <31545-done@debbugs.gnu.org>; Mon, 21 May 2018 22:54:50 +0200 (CEST) Original-Received: by localhost (Postfix, from userid 1000) id AFD662C4B3C; Mon, 21 May 2018 22:54:49 +0200 (CEST) X-Yow: Used staples are good with SOY SAUCE! In-Reply-To: <8736yl19lu.fsf@igel.home> (Andreas Schwab's message of "Mon, 21 May 2018 14:22:53 +0200") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:146359 Archived-At: I have pushed this patch to fix the GC problem in xwidget-webkit-execute-script. Andreas. * src/xwidget.h (struct xwidget): Add script_callbacks. * src/xwidget.c (save_script_callback): New function. (Fxwidget_webkit_execute_script): Use it. Encode script before passing to execution engine. Always use a callback. (webkit_javascript_finished_cb): Deallocate script. (kill_buffer_xwidgets): Deallocate remaining scripts. (Fxwidget_webkit_zoom): Doc fix. (Fxwidget_resize): Doc fix. --- src/xwidget.c | 99 +++++++++++++++++++++++++++++++++++++-------------- src/xwidget.h | 3 ++ 2 files changed, 75 insertions(+), 27 deletions(-) diff --git a/src/xwidget.c b/src/xwidget.c index 95fa5f19c4..c4a3b1990d 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -362,7 +362,7 @@ webkit_js_to_lisp (JSContextRef context, JSValueRef value) static void webkit_javascript_finished_cb (GObject *webview, GAsyncResult *result, - gpointer lisp_callback) + gpointer arg) { WebKitJavascriptResult *js_result; JSValueRef value; @@ -370,6 +370,11 @@ webkit_javascript_finished_cb (GObject *webview, GError *error = NULL; struct xwidget *xw = g_object_get_data (G_OBJECT (webview), XG_XWIDGET); + ptrdiff_t script_idx = (ptrdiff_t) arg; + Lisp_Object script_callback = AREF (xw->script_callbacks, script_idx); + ASET (xw->script_callbacks, script_idx, Qnil); + if (!NILP (script_callback)) + xfree (XSAVE_POINTER (XCAR (script_callback), 0)); js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (webview), result, &error); @@ -381,18 +386,19 @@ webkit_javascript_finished_cb (GObject *webview, return; } - context = webkit_javascript_result_get_global_context (js_result); - value = webkit_javascript_result_get_value (js_result); - Lisp_Object lisp_value = webkit_js_to_lisp (context, value); - webkit_javascript_result_unref (js_result); + if (!NILP (script_callback) && !NILP (XCDR (script_callback))) + { + context = webkit_javascript_result_get_global_context (js_result); + value = webkit_javascript_result_get_value (js_result); + Lisp_Object lisp_value = webkit_js_to_lisp (context, value); + + /* Register an xwidget event here, which then runs the callback. + This ensures that the callback runs in sync with the Emacs + event loop. */ + store_xwidget_js_callback_event (xw, XCDR (script_callback), lisp_value); + } - /* Register an xwidget event here, which then runs the callback. - This ensures that the callback runs in sync with the Emacs - event loop. */ - /* FIXME: This might lead to disaster if LISP_CALLBACK's object - was garbage collected before now. See the FIXME in - Fxwidget_webkit_execute_script. */ - store_xwidget_js_callback_event (xw, XPL (lisp_callback), lisp_value); + webkit_javascript_result_unref (js_result); } @@ -684,8 +690,7 @@ DEFUN ("xwidget-webkit-goto-uri", DEFUN ("xwidget-webkit-zoom", Fxwidget_webkit_zoom, Sxwidget_webkit_zoom, 2, 2, 0, - doc: /* Change the zoom factor of the xwidget webkit instance -referenced by XWIDGET. */) + doc: /* Change the zoom factor of the xwidget webkit instance referenced by XWIDGET. */) (Lisp_Object xwidget, Lisp_Object factor) { WEBKIT_FN_INIT (); @@ -700,12 +705,46 @@ referenced by XWIDGET. */) return Qnil; } +/* Save script and fun in the script/callback save vector and return + its index. */ +static ptrdiff_t +save_script_callback (struct xwidget *xw, Lisp_Object script, Lisp_Object fun) +{ + ptrdiff_t script_bytes = STRING_BYTES (XSTRING (script)); + char *script_data = xmalloc (script_bytes + 1); + memcpy (script_data, SSDATA (script), script_bytes + 1); + + ptrdiff_t idx; + Lisp_Object cbs = xw->script_callbacks; + if (NILP (cbs)) + xw->script_callbacks = cbs = Fmake_vector (make_number (32), Qnil); + + /* Find first free index. */ + for (idx = 0; ; idx++) + { + if (idx >= ASIZE (cbs)) + { + /* Resize script/callback save vector. */ + Lisp_Object new_cbs = Fmake_vector (make_number (idx + 32), Qnil); + ptrdiff_t n; + for (n = 0; n < idx; n++) + ASET (new_cbs, n, AREF (cbs, n)); + xw->script_callbacks = cbs = new_cbs; + } + if (NILP (AREF (cbs, idx))) + { + ASET (cbs, idx, Fcons (make_save_ptr (script_data), fun)); + break; + } + } + return idx; +} DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script, 2, 3, 0, - doc: /* Make the Webkit XWIDGET execute JavaScript SCRIPT. If -FUN is provided, feed the JavaScript return value to the single + doc: /* Make the Webkit XWIDGET execute JavaScript SCRIPT. +If FUN is provided, feed the JavaScript return value to the single argument procedure FUN.*/) (Lisp_Object xwidget, Lisp_Object script, Lisp_Object fun) { @@ -714,28 +753,24 @@ argument procedure FUN.*/) if (!NILP (fun) && !FUNCTIONP (fun)) wrong_type_argument (Qinvalid_function, fun); - GAsyncReadyCallback callback - = FUNCTIONP (fun) ? webkit_javascript_finished_cb : NULL; + script = ENCODE_SYSTEM (script); - /* FIXME: The following hack assumes USE_LSB_TAG. */ - verify (USE_LSB_TAG); - /* FIXME: This hack might lead to disaster if FUN is garbage - collected before store_xwidget_js_callback_event makes it visible - to Lisp again. See the FIXME in webkit_javascript_finished_cb. */ - gpointer callback_arg = XLP (fun); + /* Protect script and fun during GC. */ + ptrdiff_t idx = save_script_callback (xw, script, fun); /* JavaScript execution happens asynchronously. If an elisp callback function is provided we pass it to the C callback procedure that retrieves the return value. */ webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (xw->widget_osr), - SSDATA (script), + XSAVE_POINTER (XCAR (AREF (xw->script_callbacks, idx)), 0), NULL, /* cancelable */ - callback, callback_arg); + webkit_javascript_finished_cb, + (gpointer) idx); return Qnil; } DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, - doc: /* Resize XWIDGET. NEW_WIDTH, NEW_HEIGHT define the new size. */ ) + doc: /* Resize XWIDGET to NEW_WIDTH, NEW_HEIGHT. */ ) (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height) { CHECK_XWIDGET (xwidget); @@ -1197,6 +1232,16 @@ kill_buffer_xwidgets (Lisp_Object buffer) gtk_widget_destroy (xw->widget_osr); gtk_widget_destroy (xw->widgetwindow_osr); } + if (!NILP (xw->script_callbacks)) + { + ptrdiff_t idx; + for (idx = 0; idx < ASIZE (xw->script_callbacks); idx++) + { + if (!NILP (AREF (xw->script_callbacks, idx))) + xfree (XSAVE_POINTER (XCAR (AREF (xw->script_callbacks, idx)), 0)); + ASET (xw->script_callbacks, idx, Qnil); + } + } } } } diff --git a/src/xwidget.h b/src/xwidget.h index 8267012d5d..93f4cfb794 100644 --- a/src/xwidget.h +++ b/src/xwidget.h @@ -47,6 +47,9 @@ struct xwidget /* A title used for button labels, for instance. */ Lisp_Object title; + /* Vector of currently executing scripts with callbacks. */ + Lisp_Object script_callbacks; + /* Here ends the Lisp part. "height" is the marker field. */ int height; -- 2.17.0 -- Andreas Schwab, schwab@linux-m68k.org GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1 "And now for something completely different."