[Home] Shell alias values are not properly quoted

  • Done
  • quality assurance status badge
Details
3 participants
  • Ekaitz Zarraga
  • Ludovic Courtès
  • Ludovic Courtès
Owner
unassigned
Submitted by
Ludovic Courtès
Severity
normal
L
L
Ludovic Courtès wrote on 24 Apr 2023 09:57
(address . bug-guix@gnu.org)
875y9l67c5.fsf@inria.fr
Hi!

As Ekaitz reported on Mastodon, shell alias values are not properly
quoted, which causes problem when an alias value contains double-quotes
for instance:

Toggle snippet (13 lines)
(define (bash-serialize-aliases field-name val)
#~(string-append
#$@(map
(match-lambda
((key . #f)
"")
((key . #t)
#~(string-append "alias " #$key "\n"))
((key . value)
#~(string-append "alias " #$key "=\"" #$value "\"\n")))
val)))

The solution is to borrow and factorize the code of
‘environment-variable-shell-definitions’, which does it right.

Ludo’.
E
E
Ekaitz Zarraga wrote on 24 Apr 2023 12:10
(name . Ludovic Courtès)(address . ludovic.courtes@inria.fr)(address . 63048@debbugs.gnu.org)
ysOR2QV1qAMeJ5roGVJ9dGgucalDbc-dZqiy1Fxry5G1t-db79TUwoOzEbhgJ5tIqXlxCN_pfKHi3UBf7Hz-AlFjs7XI0FYfBZUVyui_WhY=@elenq.tech
As an extra note:

The problem I encountered was when the alias was defined using single quote marks:

alias ls='ls blabla "problem"'

this is parsed to:

("ls" . "blabla \"problem\"")

Which is written as:

alias ls="blabla "problem""

Which is wrong.

So the problem relies on the fact that the quotations marks have been changed from ' to " and the escaping have not been adjusted accordingly.

:)
E
E
Ekaitz Zarraga wrote on 24 Apr 2023 19:41
(name . Ludovic Courtès)(address . ludovic.courtes@inria.fr)(address . 63048@debbugs.gnu.org)
rG1_O28tWZDkb02eKEC4gH9wvuQg9BWh8rKKUmlNt6wNibGsE_WeBtjyoJ5oaLxpSJSnONPWnFPjn8pVZgWOKfy614I8hzZO6Z-7oMSL0-I=@elenq.tech
I made something like this instead of reusing the code you suggested, Ludo.
But it doesn't work. I don't really know why:

Toggle diff (37 lines)
diff --git a/guix/scripts/home/import.scm b/guix/scripts/home/import.scm
index fd263c0699..2d7a7abbf2 100644
--- a/guix/scripts/home/import.scm
+++ b/guix/scripts/home/import.scm
@@ -64,12 +64,23 @@ (define (destination-append path)
(define alias-rx
(make-regexp "^alias ([^=]+)=[\"'](.+)[\"']$"))
+ (define (quote-style line)
+ (cond
+ ((string-match "^alias ([^=]+)=[\"].*$" line) 'double)
+ ((string-match "^alias ([^=]+)=['].*$" line) 'single)))
+
(define (bash-alias->pair line)
(match (regexp-exec alias-rx line)
(#f #f)
(matched
`(,(match:substring matched 1) . ,(match:substring matched 2)))))
+ (define (escape-alias-body quote-style body)
+ (if (eq? quote-style 'single)
+ (let* ((escaped-dquotes (string-replace-substring body "\"" "\\\"")))
+ (string-replace-substring escaped-dquotes "\\'" "'"))
+ body))
+
(define (parse-aliases input)
(let loop ((result '()))
(match (read-line input)
@@ -78,7 +89,7 @@ (define (parse-aliases input)
(line
(match (bash-alias->pair line)
(#f (loop result))
- (alias (loop (cons alias result))))))))
+ (alias (loop (cons alias (escape-alias-body (quote-style line) result)))))))))
(let ((rc (destination-append ".bashrc"))
(profile (destination-append ".bash_profile"))
L
L
Ludovic Courtès wrote on 6 Jul 2023 17:01
[PATCH] home: services: bash: Properly quote shell aliases.
(address . 63048@debbugs.gnu.org)
ccd45825fa1739631584cb6a357bc7782217c8aa.1688655471.git.ludo@gnu.org
From: Ludovic Courtès <ludovic.courtes@inria.fr>

Reported by Ekaitz Zarraga <ekaitz@elenq.tech>.

* gnu/home/services.scm (with-shell-quotation-bindings): New procedure.
(environment-variable-shell-definitions): Use it instead of inline copy.
* gnu/home/services/shells.scm (bash-serialize-aliases): Use it. Add
clause for 'literal-string?'.
* tests/guix-home.sh: Add 'aliases' to 'home-bash-extension' and test it.
---
gnu/home/services.scm | 53 ++++++++++++++++++++----------------
gnu/home/services/shells.scm | 28 ++++++++++++-------
tests/guix-home.sh | 7 ++++-
3 files changed, 54 insertions(+), 34 deletions(-)

Hi!

Here's a patch that fixes it. AFAICS 'guix home import' does the right
thing, so this is really just fixing the way aliases are serialized.

Let me know what you think!

Ludo'.

Toggle diff (153 lines)
diff --git a/gnu/home/services.scm b/gnu/home/services.scm
index b17a34d19d..042eba4780 100644
--- a/gnu/home/services.scm
+++ b/gnu/home/services.scm
@@ -53,6 +53,7 @@ (define-module (gnu home services)
literal-string?
literal-string-value
+ with-shell-quotation-bindings
environment-variable-shell-definitions
home-files-directory
xdg-configuration-files-directory
@@ -183,11 +184,10 @@ (define-record-type <literal-string>
literal-string?
(str literal-string-value))
-(define (environment-variable-shell-definitions variables)
- "Return a gexp that evaluates to a list of POSIX shell statements defining
-VARIABLES, a list of environment variable name/value pairs. The returned code
-ensures variable values are properly quoted."
- #~(let* ((quote-string
+(define (with-shell-quotation-bindings exp)
+ "Insert EXP, a gexp, in a lexical environment providing the
+'shell-single-quote' and 'shell-double-quote' bindings."
+#~(let* ((quote-string
(lambda (value quoted-chars)
(list->string (string-fold-right
(lambda (chr lst)
@@ -206,24 +206,31 @@ (define (environment-variable-shell-definitions variables)
;; Single-quote VALUE to enter a literal string.
(string-append "'" (quote-string value '(#\'))
"'"))))
- (string-append
- #$@(map (match-lambda
- ((key . #f)
- "")
- ((key . #t)
- #~(string-append "export " #$key "\n"))
- ((key . (or (? string? value)
- (? file-like? value)
- (? gexp? value)))
- #~(string-append "export " #$key "="
- (shell-double-quote #$value)
- "\n"))
- ((key . (? literal-string? value))
- #~(string-append "export " #$key "="
- (shell-single-quote
- #$(literal-string-value value))
- "\n")))
- variables))))
+ #$exp))
+
+(define (environment-variable-shell-definitions variables)
+ "Return a gexp that evaluates to a list of POSIX shell statements defining
+VARIABLES, a list of environment variable name/value pairs. The returned code
+ensures variable values are properly quoted."
+ (with-shell-quotation-bindings
+ #~(string-append
+ #$@(map (match-lambda
+ ((key . #f)
+ "")
+ ((key . #t)
+ #~(string-append "export " #$key "\n"))
+ ((key . (or (? string? value)
+ (? file-like? value)
+ (? gexp? value)))
+ #~(string-append "export " #$key "="
+ (shell-double-quote #$value)
+ "\n"))
+ ((key . (? literal-string? value))
+ #~(string-append "export " #$key "="
+ (shell-single-quote
+ #$(literal-string-value value))
+ "\n")))
+ variables))))
(define (environment-variables->setup-environment-script vars)
"Return a file that can be sourced by a POSIX compliant shell which
diff --git a/gnu/home/services/shells.scm b/gnu/home/services/shells.scm
index 415b5470c5..7960590e7c 100644
--- a/gnu/home/services/shells.scm
+++ b/gnu/home/services/shells.scm
@@ -313,16 +313,24 @@ (define home-zsh-service-type
;;;
(define (bash-serialize-aliases field-name val)
- #~(string-append
- #$@(map
- (match-lambda
- ((key . #f)
- "")
- ((key . #t)
- #~(string-append "alias " #$key "\n"))
- ((key . value)
- #~(string-append "alias " #$key "=\"" #$value "\"\n")))
- val)))
+ (with-shell-quotation-bindings
+ #~(string-append
+ #$@(map
+ (match-lambda
+ ((key . #f)
+ "")
+ ((key . #t)
+ #~(string-append "alias " #$key "\n"))
+ ((key . (? literal-string? value))
+ #~(string-append "alias " #$key "="
+ (shell-single-quote
+ #$(literal-string-value value))
+ "\n"))
+ ((key . value)
+ #~(string-append "alias " #$key "="
+ (shell-double-quote #$value)
+ "\n")))
+ val))))
(define-configuration home-bash-configuration
(package
diff --git a/tests/guix-home.sh b/tests/guix-home.sh
index e9ef76c862..e6d16d7fab 100644
--- a/tests/guix-home.sh
+++ b/tests/guix-home.sh
@@ -1,7 +1,7 @@
# GNU Guix --- Functional package management for GNU
# Copyright © 2021-2023 Andrew Tropin <andrew@trop.in>
# Copyright © 2021 Oleg Pykhalov <go.wigust@gmail.com>
-# Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
+# Copyright © 2022, 2023 Ludovic Courtès <ludo@gnu.org>
#
# This file is part of GNU Guix.
#
@@ -94,6 +94,9 @@ trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT
(home-bash-extension
(environment-variables
'(("PS1" . "$GUIX_ENVIRONMENT λ ")))
+ (aliases
+ `(("run" . "guix shell")
+ ("path" . ,(literal-string "echo $PATH"))))
(bashrc
(list
(plain-file
@@ -149,6 +152,8 @@ EOF
test -d "${HOME}/.guix-home"
test -h "${HOME}/.bash_profile"
test -h "${HOME}/.bashrc"
+ grep 'alias run="guix shell"' "$HOME/.bashrc"
+ grep "alias path='echo \$PATH'" "$HOME/.bashrc"
test "$(tail -n 2 "${HOME}/.bashrc")" == "\
# dot-bashrc test file for guix home
# the content of bashrc-test-config.sh"

base-commit: 2426e51688d479042ea115a634c6be2d8b9f3b99
--
2.40.1
L
L
Ludovic Courtès wrote on 11 Jul 2023 17:02
Re: bug#63048: [Home] Shell alias values are not properly quoted
(address . 63048-done@debbugs.gnu.org)
87ilaq3305.fsf_-_@gnu.org
Ludovic Courtès <ludo@gnu.org> skribis:

Toggle quote (11 lines)
> From: Ludovic Courtès <ludovic.courtes@inria.fr>
>
> Fixes <https://issues.guix.gnu.org/63048>.
> Reported by Ekaitz Zarraga <ekaitz@elenq.tech>.
>
> * gnu/home/services.scm (with-shell-quotation-bindings): New procedure.
> (environment-variable-shell-definitions): Use it instead of inline copy.
> * gnu/home/services/shells.scm (bash-serialize-aliases): Use it. Add
> clause for 'literal-string?'.
> * tests/guix-home.sh: Add 'aliases' to 'home-bash-extension' and test it.

Pushed as 7d9fdfb19d17dc99a4cf2548942c4f8ae7433572!

Ludo'.
Closed
?