|
| 1 | +diff --git a/lisp/files.el b/lisp/files.el |
| 2 | +index 5536af0..5e0d44d 100644 |
| 3 | +--- a/lisp/files.el |
| 4 | ++++ b/lisp/files.el |
| 5 | +@@ -702,6 +702,54 @@ buffer contents as untrusted. |
| 6 | + |
| 7 | + This variable might be subject to change without notice.") |
| 8 | + (put 'untrusted-content 'permanent-local t) |
| 9 | ++(defcustom trusted-files nil |
| 10 | ++ "List of files and directories whose content we trust. |
| 11 | ++Be extra careful here since trusting means that Emacs might execute the |
| 12 | ++code contained within those files and directories without an explicit |
| 13 | ++request by the user. |
| 14 | ++One important case when this might happen is when `flymake-mode' is |
| 15 | ++enabled (for example, when it is added to a mode hook). |
| 16 | ++Each element of the list should be a string: |
| 17 | ++- If it ends in \"/\", it is considered as a directory name and means that |
| 18 | ++ Emacs should trust all the files whose name has this directory as a prefix. |
| 19 | ++- else it is considered as a file name. |
| 20 | ++Use abbreviated file names. For example, an entry \"~/mycode\" means |
| 21 | ++that Emacs will trust all the files in your directory \"mycode\". |
| 22 | ++This variable can also be set to `:all', in which case Emacs will trust |
| 23 | ++all files, which opens a gaping security hole." |
| 24 | ++ :type '(choice (repeat :tag "List" file) |
| 25 | ++ (const :tag "Trust everything (DANGEROUS!)" :all)) |
| 26 | ++ :version "30.1") |
| 27 | ++(put 'trusted-files 'risky-local-variable t) |
| 28 | ++ |
| 29 | ++(defun trusted-content-p () |
| 30 | ++ "Return non-nil if we trust the contents of the current buffer. |
| 31 | ++Here, \"trust\" means that we are willing to run code found inside of it. |
| 32 | ++See also `trusted-files'." |
| 33 | ++ ;; We compare with `buffer-file-truename' i.s.o `buffer-file-name' |
| 34 | ++ ;; to try and avoid marking as trusted a file that's merely accessed |
| 35 | ++ ;; via a symlink that happens to be inside a trusted dir. |
| 36 | ++ (and (not untrusted-content) |
| 37 | ++ buffer-file-truename |
| 38 | ++ (with-demoted-errors "trusted-content-p: %S" |
| 39 | ++ (let ((exists (file-exists-p buffer-file-truename))) |
| 40 | ++ (or |
| 41 | ++ (eq trusted-files :all) |
| 42 | ++ ;; We can't avoid trusting the user's init file. |
| 43 | ++ (if (and exists user-init-file) |
| 44 | ++ (file-equal-p buffer-file-truename user-init-file) |
| 45 | ++ (equal buffer-file-truename user-init-file)) |
| 46 | ++ (let ((file (abbreviate-file-name buffer-file-truename)) |
| 47 | ++ (trusted nil)) |
| 48 | ++ (dolist (tf trusted-files) |
| 49 | ++ (when (or (if exists (file-equal-p tf file) (equal tf file)) |
| 50 | ++ ;; We don't use `file-in-directory-p' here, because |
| 51 | ++ ;; we want to err on the conservative side: "guilty |
| 52 | ++ ;; until proven innocent". |
| 53 | ++ (and (string-suffix-p "/" tf) |
| 54 | ++ (string-prefix-p tf file))) |
| 55 | ++ (setq trusted t))) |
| 56 | ++ trusted)))))) |
| 57 | + |
| 58 | + ;; This is an odd variable IMO. |
| 59 | + ;; You might wonder why it is needed, when we could just do: |
| 60 | +diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el |
| 61 | +index 7436fe7..230992f 100644 |
| 62 | +--- a/lisp/progmodes/elisp-mode.el |
| 63 | ++++ b/lisp/progmodes/elisp-mode.el |
| 64 | +@@ -430,6 +430,34 @@ be used instead. |
| 65 | + |
| 66 | + (defvar warning-minimum-log-level) |
| 67 | + |
| 68 | ++(defvar elisp--macroexpand-untrusted-warning t) |
| 69 | ++ |
| 70 | ++(defun elisp--safe-macroexpand-all (sexp) |
| 71 | ++ (if (not (trusted-content-p)) |
| 72 | ++ ;; FIXME: We should try and do better here, either using a notion |
| 73 | ++ ;; of "safe" macros, or with `bwrap', or ... |
| 74 | ++ (progn |
| 75 | ++ (when elisp--macroexpand-untrusted-warning |
| 76 | ++ (setq-local elisp--macroexpand-untrusted-warning nil) ;Don't spam! |
| 77 | ++ (message "Completion of local vars is disabled in %s (untrusted content)" |
| 78 | ++ (buffer-name))) |
| 79 | ++ sexp) |
| 80 | ++ (let ((macroexpand-advice |
| 81 | ++ (lambda (expander form &rest args) |
| 82 | ++ (condition-case err |
| 83 | ++ (apply expander form args) |
| 84 | ++ (error |
| 85 | ++ (message "Ignoring macroexpansion error: %S" err) form))))) |
| 86 | ++ (unwind-protect |
| 87 | ++ ;; Silence any macro expansion errors when |
| 88 | ++ ;; attempting completion at point (bug#58148). |
| 89 | ++ (let ((inhibit-message t) |
| 90 | ++ (macroexp-inhibit-compiler-macros t) |
| 91 | ++ (warning-minimum-log-level :emergency)) |
| 92 | ++ (advice-add 'macroexpand-1 :around macroexpand-advice) |
| 93 | ++ (macroexpand-all sexp elisp--local-macroenv)) |
| 94 | ++ (advice-remove 'macroexpand-1 macroexpand-advice))))) |
| 95 | ++ |
| 96 | + (defun elisp--local-variables () |
| 97 | + "Return a list of locally let-bound variables at point." |
| 98 | + (save-excursion |
| 99 | +@@ -445,22 +473,7 @@ be used instead. |
| 100 | + (car (read-from-string |
| 101 | + (concat txt "elisp--witness--lisp" closer))) |
| 102 | + ((invalid-read-syntax end-of-file) nil))) |
| 103 | +- (macroexpand-advice (lambda (expander form &rest args) |
| 104 | +- (condition-case nil |
| 105 | +- (apply expander form args) |
| 106 | +- (error form)))) |
| 107 | +- (sexp |
| 108 | +- (unwind-protect |
| 109 | +- ;; Silence any macro expansion errors when |
| 110 | +- ;; attempting completion at point (bug#58148). |
| 111 | +- (let ((inhibit-message t) |
| 112 | +- (warning-minimum-log-level :emergency)) |
| 113 | +- (advice-add 'macroexpand :around macroexpand-advice) |
| 114 | +- (condition-case nil |
| 115 | +- (macroexpand-all sexp) |
| 116 | +- (error sexp))) |
| 117 | +- (advice-remove 'macroexpand macroexpand-advice))) |
| 118 | +- (vars (elisp--local-variables-1 nil sexp))) |
| 119 | ++ (vars (elisp--local-variables-1 nil (elisp--safe-macroexpand-all sexp)))) |
| 120 | + (delq nil |
| 121 | + (mapcar (lambda (var) |
| 122 | + (and (symbolp var) |
| 123 | +@@ -2164,6 +2177,14 @@ directory of the buffer being compiled, and nothing else.") |
| 124 | + "A Flymake backend for elisp byte compilation. |
| 125 | + Spawn an Emacs process that byte-compiles a file representing the |
| 126 | + current buffer state and calls REPORT-FN when done." |
| 127 | ++ (unless (trusted-content-p) |
| 128 | ++ ;; FIXME: Use `bwrap' and friends to compile untrusted content. |
| 129 | ++ ;; FIXME: We emit a message *and* signal an error, because by default |
| 130 | ++ ;; Flymake doesn't display the warning it puts into "*flmake log*". |
| 131 | ++ (message "Disabling elisp-flymake-byte-compile in %s (untrusted content)" |
| 132 | ++ (buffer-name)) |
| 133 | ++ (error "Disabling elisp-flymake-byte-compile in %s (untrusted content)" |
| 134 | ++ (buffer-name))) |
| 135 | + (when elisp-flymake--byte-compile-process |
| 136 | + (when (process-live-p elisp-flymake--byte-compile-process) |
| 137 | + (kill-process elisp-flymake--byte-compile-process))) |
0 commit comments