From f61fa503365e305c566d0dc366f78e3a640680fd Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 29 Apr 2020 19:39:35 -0400 Subject: [PATCH] Null-byte delimit envvar file lines This prevents issues with multi-line envvar values. --- core/cli/env.el | 7 ++++--- core/core.el | 46 ++++++++++++++++++---------------------------- 2 files changed, 22 insertions(+), 31 deletions(-) diff --git a/core/cli/env.el b/core/cli/env.el index bb546ede1..f13a838d3 100644 --- a/core/cli/env.el +++ b/core/cli/env.el @@ -113,10 +113,11 @@ default, on Linux, this is '$SHELL -ic /usr/bin/env'. Variables in "# run 'doom sync'. To create a safe-to-edit envvar file use:\n#\n" "# doom env -o ~/.doom.d/myenv\n#\n" "# And load it with (doom-load-envvars-file \"~/.doom.d/myenv\").\n") - (concat "# This file is safe to edit by hand, but needs to be loaded manually with:\n#\n" + (concat "# This file is safe to edit by hand, but remember to preserve the null bytes at\n" + "# the end of each line! needs to be loaded manually with:\n#\n" "# (doom-load-envvars-file \"path/to/this/file\")\n#\n" "# Use 'doom env -o path/to/this/file' to regenerate it.")) - "# ---------------------------------------------------------------------------\n\n")) + "# ---------------------------------------------------------------------------\n\0\n")) ;; We assume that this noninteractive session was spawned from the ;; user's interactive shell, therefore we just dump ;; `process-environment' to a file. @@ -124,7 +125,7 @@ default, on Linux, this is '$SHELL -ic /usr/bin/env'. Variables in (if (cl-find-if (doom-rpartial #'string-match-p (car (split-string env "="))) doom-env-ignored-vars) (print! (info "Ignoring %s") env) - (insert env "\n"))) + (insert env "\0\n"))) (print! (success "Successfully generated %S") (path env-file)) t)))))) diff --git a/core/core.el b/core/core.el index 288013d96..437779996 100644 --- a/core/core.el +++ b/core/core.el @@ -465,34 +465,24 @@ If NOERROR is non-nil, don't throw an error if the file doesn't exist or is unreadable. Returns the names of envvars that were changed." (if (not (file-readable-p file)) (unless noerror - (signal 'file-error (list "Couldn't read envvar file" file))) - (let (envvars environment) - (with-temp-buffer - (save-excursion - (insert "\n") - (insert-file-contents file)) - (while (re-search-forward "\n *\\([^#= \n]*\\)=" nil t) - (push (match-string 1) envvars) - (push (buffer-substring - (match-beginning 1) - (1- (or (save-excursion - (when (re-search-forward "^\\([^= ]+\\)=" nil t) - (line-beginning-position))) - (point-max)))) - environment))) - (when environment - (setq process-environment - (append (nreverse environment) process-environment) - exec-path - (if (member "PATH" envvars) - (append (split-string (getenv "PATH") path-separator t) - (list exec-directory)) - exec-path) - shell-file-name - (if (member "SHELL" envvars) - (or (getenv "SHELL") shell-file-name) - shell-file-name)) - envvars)))) + (signal 'file-error (list "No envvar file exists" file))) + (when-let + (env + (with-temp-buffer + (save-excursion + (insert "\0\n") ; to prevent off-by-one + (insert-file-contents file)) + (save-match-data + (when (re-search-forward "\0\n *\\([^#= \n]*\\)=" nil t) + (setq + env (split-string (buffer-substring (match-beginning 1) (point-max)) + "\0\n" + 'omit-nulls)))))) + (setq process-environment (append (nreverse env) process-environment) + exec-path (append (split-string (getenv "PATH") path-separator t) + (list exec-directory)) + shell-file-name (or (getenv "SHELL") shell-file-name)) + env))) (defun doom-initialize (&optional force-p noerror) "Bootstrap Doom, if it hasn't already (or if FORCE-P is non-nil).