all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Philip Kaludercic <philipk@posteo.net>
To: Lars Ingebrigtsen <larsi@gnus.org>
Cc: 58506@debbugs.gnu.org, Robert Pluim <rpluim@gmail.com>,
	Juri Linkov <juri@linkov.net>,
	Stefan Kangas <stefankangas@gmail.com>,
	Stefan Monnier <monnier@iro.umontreal.ca>
Subject: bug#58506: Use ".dir-locals.eld" and ".dir-locals-2.eld" when they exist
Date: Sat, 15 Oct 2022 15:12:12 +0000	[thread overview]
Message-ID: <877d115df7.fsf@posteo.net> (raw)
In-Reply-To: <87wn912nsc.fsf@gnus.org> (Lars Ingebrigtsen's message of "Sat, 15 Oct 2022 15:56:35 +0200")

[-- Attachment #1: Type: text/plain, Size: 819 bytes --]

Lars Ingebrigtsen <larsi@gnus.org> writes:

> Philip Kaludercic <philipk@posteo.net> writes:
>
>> Another idea could be to take inspiration from Guile's "Sandboxed
>> Evaluation"[0] and provide a "safe subset" of Elisp that can be
>> evaluated (with some additional checks).
>>
>> E.g. the following would allow evaluating `add-to-list' if the list if
>> safe and the value is self-evaluating:
>
> Oh, that's a good idea.  I wonder whether anybody's written an
> interpreter for a "safe" version of Emacs Lisp -- then people could put
> `if' statements etc also into these files.

There is unsafep, but that is too strict for what we want.  E.g.

  (unsafep '(setq tab-width 3)) ;; => (global-variable tab-width)

even though we would want this to work.  I've attached an incomplete
sketch of how this could look like


[-- Attachment #2: safe-eval.el --]
[-- Type: text/plain, Size: 3796 bytes --]

;;; safe-eval.el --- Evaluation of Safe Emacs Lisp   -*- lexical-binding: t; -*-

;; Copyright (C) 2022  Philip Kaludercic

;; Author: Philip Kaludercic <philipk@posteo.net>
;; Created: 15Oct22
;; Keywords: lisp

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; An evaluator for safe Emacs Lisp code.

;;; Code:

(eval-when-compile (require 'pcase))
(require 'cl-lib)
(require 'seq)
(require 'macroexp)

(cl-defgeneric safe-eval-p (form)
  "Return non-nil if it is safe to evaluate FORM.
A FORM is safe if it is not a function call, has no side-effects
or a method has been defined to verify its safety."
  (:method :around (form)
	   "Macroexpand FORM before testing for safety."
	   (cl-call-next-method (macroexpand-all form)))
  ;; Some basic logic
  (:method
   ((form (head if)))
   "A `if' FORM is safe if all arguments are safe."
   (pcase-let ((`(if ,(pred safe-eval-p) ,(pred safe-eval-p) . ,else) form))
     (seq-every-p #'safe-eval-p else)))
  (:method
   ((form (head when)))
   "A `when' FORM is safe if all arguments are safe."
   (pcase-let ((`(when ,(pred safe-eval-p) . ,body) form))
     (seq-every-p #'safe-eval-p body)))
  (:method
   ((form (head unless)))
   "A `unless' FORM is safe if all arguments are safe."
   (pcase-let ((`(unless ,(pred safe-eval-p) . ,body) form))
     (seq-every-p #'safe-eval-p body)))
  ;; Common state modifiers
  (:method
   ((form (head setq)))
   "A `setq' FORM is safe the new value is a safe value."
   (pcase-let ((`(setq ,var ,val) form))
     (and (safe-eval-p val)
	  (safe-local-variable-p var val))))
  (:method
   ((form (head add-hook)))
   "A form with `add-hook' must modify a hook locally."
   (pcase-let* ((`(add-hook ',hook
			    ,(or `#',func `',func)
			    ,(pred macroexp-const-p)
			    ,(and (pred macroexp-const-p)
				  (pred identity)))
		 form)
		(new-hook (cons func (symbol-value hook))))
     (and (safe-local-variable-p hook new-hook)
	  (macroexp-const-p func))))
  (:method
   ((form (head add-to-list)))
   "A `add-to-hook' FORM is safe the new list is has a safe value."
   (pcase-let* ((`(add-to-list ',list-var ,element ,append)
		 form)
		(old-list (symbol-value list-var))
		(new-list (if append
			      (append old-list (list element))
			    (cons element old-list))))
     ;; FIXME: `new-list' contains `element' before evaluation.
     (and (safe-local-variable-p list-var new-list)
	  (safe-eval-p element)
	  (macroexp-const-p append))))
  ;; ;; Fallback
  (:method
   ((form t))
   "A fallback handler to check if FORM is side-effect free."
   (or (not (consp form))
       (and (get (car form) 'side-effect-free)
	    (seq-every-p #'safe-eval-p (cdr form))))))

;;;###autoload
(defun safe-eval (form)
  "Evaluate FORM is it is safe per `safe-eval-p'.
If it is not safe, it will be silently ignored."
  (when (safe-eval-p form)
    (eval form t)))

;;;###autoload
(defun safe-eval-file (filename)
  "Evaluate the safe contents of FILENAME.
All files deemed unsafe by `safe-eval-p' are silently ignored.'"
  (with-temp-buffer
    (insert-file-contents filename)
    (while (not (eobp))
      (safe-eval (read (current-buffer))))))

(provide 'safe-eval)
;;; safe-eval.el ends here

[-- Attachment #3: Type: text/plain, Size: 1059 bytes --]


> We already mark functions as being side-effect-free, so it seems like
> code like
>
> (if (cl-oddp (% (random) 2))
>     (setq ...))
>
> would be "safe" together with the safep markup for assignments we
> already have.  We could make a safe restricted language subset for use
> both here and in similar circumstances.

That is a good point, but I think more tagging should be done.  Ideally
this would read as regular elisp (which is kind of ironic considering
that we are discussing an .eld file), so it would be nice if
mode-specific modifications could be done by just writing

--8<---------------cut here---------------start------------->8---
(when (derived-mode-p 'c-mode)
  (setq tab-width 8))
--8<---------------cut here---------------end--------------->8---

or something like that.

>> No, what I had in mind was not to trigger warnings but either to
>> highlight unused variables or provide a command that would check it for
>> you.
>
> Oh, right.  That's another good idea.  😀

One idea would be to use Flymake.

  reply	other threads:[~2022-10-15 15:12 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-13  9:05 bug#58486: [PATCH] Prevent .dir-locals.el from being byte-compiled Philip Kaludercic
2022-10-13 14:20 ` Stefan Kangas
2022-10-13 14:32   ` Philip Kaludercic
2022-10-13 14:51     ` Stefan Kangas
2022-10-13 17:18   ` Juri Linkov
2022-10-13 19:11     ` Philip Kaludercic
2022-10-14  9:22     ` bug#58506: Use ".dir-locals.eld" and ".dir-locals-2.eld" when they exist Stefan Kangas
2022-10-14 10:38       ` Eli Zaretskii
2022-10-14 12:36         ` Stefan Kangas
2022-10-14 11:25       ` Lars Ingebrigtsen
2022-10-14 12:36         ` Stefan Kangas
2022-10-14 13:04         ` Robert Pluim
2022-10-14 13:10           ` Lars Ingebrigtsen
2022-10-14 13:23             ` Robert Pluim
2022-10-14 13:29               ` Lars Ingebrigtsen
2022-10-14 13:41                 ` Robert Pluim
2022-10-14 15:13           ` Philip Kaludercic
2022-10-15  9:18             ` Lars Ingebrigtsen
2022-10-15  9:38               ` Philip Kaludercic
2022-10-15  9:42                 ` Lars Ingebrigtsen
2022-10-15 10:00                   ` Lars Ingebrigtsen
2022-10-15 11:35                   ` Philip Kaludercic
2022-10-15 13:56                     ` Lars Ingebrigtsen
2022-10-15 15:12                       ` Philip Kaludercic [this message]
2022-10-15 16:22                         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-16  8:39                         ` Lars Ingebrigtsen
2022-10-15 10:05                 ` Stefan Kangas
2022-10-15 15:19               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-16  8:47                 ` Lars Ingebrigtsen
2022-10-16  9:34                   ` Philip Kaludercic
2022-10-16  9:43                     ` Lars Ingebrigtsen
2022-10-16 13:38                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-16 13:44                     ` Lars Ingebrigtsen
2022-10-18 13:30                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-18  7:28                 ` Juri Linkov
2022-10-18 13:25                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-14 13:38         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-14 15:07       ` Philip Kaludercic
2022-10-14 16:32     ` bug#58486: [PATCH] Prevent .dir-locals.el from being byte-compiled Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-15 19:16       ` Juri Linkov
2022-10-16 13:17         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-13 18:02 ` Lars Ingebrigtsen
2022-10-14 18:14   ` Philip Kaludercic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=877d115df7.fsf@posteo.net \
    --to=philipk@posteo.net \
    --cc=58506@debbugs.gnu.org \
    --cc=juri@linkov.net \
    --cc=larsi@gnus.org \
    --cc=monnier@iro.umontreal.ca \
    --cc=rpluim@gmail.com \
    --cc=stefankangas@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.