~ruther/guix-local

d111a6a60d3535933e4b6eba7007519b3e9d6835 — Lars-Dominik Braun 8 months ago 82918e4
guix: toml: Fix keys with embedded escape codes.

Quoted keys are treated by the specification like ordinary strings,
so escape codes must be handled as well.

* guix/build/toml.scm (eval-value): Move string escape handling…
(eval-value): …here.
(eval-toml-file): Un-escape quoted keys.
* tests/toml.scm ("parse-toml: Quoted keys with escapes"): New testcase.

Fixes: guix/guix#2414
Change-Id: I612e415cc93207bbdd18b6ec8279255fee16670a
Signed-off-by: Sharlatan Hellseher <sharlatanus@gmail.com>
2 files changed, 24 insertions(+), 12 deletions(-)

M guix/build/toml.scm
M tests/toml.scm
M guix/build/toml.scm => guix/build/toml.scm +18 -12
@@ 361,6 361,21 @@ the list KEY. For instance a KEY (a b) would retrieve alist[a][b]."
               (string->number minute)) 60))
         (#f #f)))))

  (define (eval-string value)
    "Turn a list of string tokens into an actual, flat string value by
evaluating escape codes."
    (apply string-append
           (map (match-lambda
                 (('escaped "\"") "\"")
                 (('escaped "\\") "\\")
                 (('escaped "b") "\b")
                 (('escaped "t") "\t")
                 (('escaped "n") "\n")
                 (('escaped (? (lambda (x) (>= (string-length x) 4)) u))
                  (list->string (list (integer->char (string->number u 16)))))
                 ((? string? s) s))
                (keyword-flatten '(escaped) value))))

  (define (eval-value value)
    "Evaluate right-hand-side of 'keyval token (i.e., a value)."
    (match value


@@ 395,17 410,7 @@ the list KEY. For instance a KEY (a b) would retrieve alist[a][b]."
      (('local-time rest ...)
       (eval-date rest))
      (('string str ...)
       (apply string-append
              (map (match-lambda
                    (('escaped "\"") "\"")
                    (('escaped "\\") "\\")
                    (('escaped "b") "\b")
                    (('escaped "t") "\t")
                    (('escaped "n") "\n")
                    (('escaped (? (lambda (x) (>= (string-length x) 4)) u))
                     (list->string (list (integer->char (string->number u 16)))))
                    ((? string? s) s))
                   (keyword-flatten '(escaped) str))))
       (eval-string str))
      ('string "")
      (('array tails ...)
       (map eval-value (keyword-flatten '(boolean integer float string array


@@ 427,7 432,8 @@ the list KEY. For instance a KEY (a b) would retrieve alist[a][b]."
     (map
      (match-lambda
        (('simple-key 'quoted-key) "")
        (('simple-key ('quoted-key k)) k)
        ;; Quoted keys are just ordinary strings and can contain escape codes.
        (('simple-key ('quoted-key rest ...)) (eval-string rest))
        (('simple-key (? string? k)) k)
        (other (raise-exception `(invalid-simple-key ,other))))
      (keyword-flatten '(simple-key) keys)))

M tests/toml.scm => tests/toml.scm +6 -0
@@ 54,6 54,12 @@ bare-key = \"value\"
'key2' = \"value\"
'quoted \"value\"' = \"value\""))

(test-equal "parse-toml: Quoted keys with escapes"
  '(("key \\ with \n escapes" . "value")
    ("key" ("with \t escapes" ("and \n dots" . "value"))))
  (parse-toml "\"key \\\\ with \\n escapes\" = \"value\"
key.\"with \\t escapes\".\"and \\n dots\" = \"value\""))

(test-equal "parse-toml: No key"
  #f
  (parse-toml "= \"no key name\""))