grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v4 1/2] json: Add function to unescape JSON-encoded strings


From: Glenn Washburn
Subject: Re: [PATCH v4 1/2] json: Add function to unescape JSON-encoded strings
Date: Mon, 6 Jun 2022 12:17:11 -0500

On Mon, 6 Jun 2022 07:28:56 +0200
Patrick Steinhardt <ps@pks.im> wrote:

> JSON strings require certain characters to be encoded, either by using a
> single reverse solidus character "\" for a set of popular characters, or
> by using a Unicode representation of "\uXXXXX". The jsmn library doesn't
> handle unescaping for us, so we must implement this functionality for
> ourselves.
> 
> Add a new function `grub_json_unescape ()` that takes a potentially
> escaped JSON string as input and returns a new unescaped string.
> 
> Signed-off-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Glenn Washburn <development@efficientek.com>

Glenn

> ---
>  grub-core/lib/json/json.c | 101 ++++++++++++++++++++++++++++++++++++++
>  grub-core/lib/json/json.h |  12 +++++
>  2 files changed, 113 insertions(+)
> 
> diff --git a/grub-core/lib/json/json.c b/grub-core/lib/json/json.c
> index 1c20c75ea..adb4747a4 100644
> --- a/grub-core/lib/json/json.c
> +++ b/grub-core/lib/json/json.c
> @@ -262,3 +262,104 @@ grub_json_getint64 (grub_int64_t *out, const 
> grub_json_t *parent, const char *ke
>  
>    return GRUB_ERR_NONE;
>  }
> +
> +grub_err_t
> +grub_json_unescape (char **out, grub_size_t *outlen, const char *in, 
> grub_size_t inlen)
> +{
> +  grub_err_t ret = GRUB_ERR_NONE;
> +  grub_size_t inpos, resultpos;
> +  char *result;
> +
> +  if (!out || !outlen)
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Output parameters are not 
> set");
> +
> +  result = grub_calloc (1, inlen + 1);
> +  if (!result)
> +    return GRUB_ERR_OUT_OF_MEMORY;
> +
> +  for (inpos = resultpos = 0; inpos < inlen; inpos++)
> +    {
> +      if (in[inpos] == '\\')
> +     {
> +       inpos++;
> +       if (inpos >= inlen)
> +         {
> +           ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Expected escaped 
> character");
> +           goto err;
> +         }
> +
> +       switch (in[inpos])
> +         {
> +           case '"':
> +             result[resultpos++] = '"'; break;
> +           case '/':
> +             result[resultpos++] = '/'; break;
> +           case '\\':
> +             result[resultpos++] = '\\'; break;
> +           case 'b':
> +             result[resultpos++] = '\b'; break;
> +           case 'f':
> +             result[resultpos++] = '\f'; break;
> +           case 'r':
> +             result[resultpos++] = '\r'; break;
> +           case 'n':
> +             result[resultpos++] = '\n'; break;
> +           case 't':
> +             result[resultpos++] = '\t'; break;
> +           case 'u':
> +             {
> +               unsigned char values[4] = {0};
> +               int i;
> +
> +               inpos++;
> +               if (inpos + ARRAY_SIZE(values) > inlen)
> +                 {
> +                   ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unicode 
> sequence too short");
> +                   goto err;
> +                 }
> +
> +               for (i = 0; i < 4; i++)
> +                 {
> +                   char c = in[inpos++];
> +
> +                   if (c >= '0' && c <= '9')
> +                     values[i] = c - '0';
> +                   else if (c >= 'A' && c <= 'F')
> +                     values[i] = c - 'A' + 10;
> +                   else if (c >= 'a' && c <= 'f')
> +                     values[i] = c - 'a' + 10;
> +                   else
> +                     {
> +                       ret = grub_error (GRUB_ERR_BAD_ARGUMENT,
> +                                         "Unicode sequence with invalid 
> character '%c'", c);
> +                       goto err;
> +                     }
> +                 }
> +
> +               if (values[0] != 0 || values[1] != 0)
> +                 result[resultpos++] = values[0] << 4 | values[1];
> +               result[resultpos++] = values[2] << 4 | values[3];
> +
> +               /* Offset the increment that's coming in via the loop 
> increment. */
> +               inpos--;
> +
> +               break;
> +             }
> +           default:
> +             ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unrecognized escaped 
> character '%c'", in[inpos]);
> +             goto err;
> +         }
> +     }
> +      else
> +       result[resultpos++] = in[inpos];
> +    }
> +
> +  *out = result;
> +  *outlen = resultpos;
> +
> +err:
> +  if (ret != GRUB_ERR_NONE)
> +    grub_free (result);
> +
> +  return ret;
> +}
> diff --git a/grub-core/lib/json/json.h b/grub-core/lib/json/json.h
> index 4ea2a22d8..626074c35 100644
> --- a/grub-core/lib/json/json.h
> +++ b/grub-core/lib/json/json.h
> @@ -125,4 +125,16 @@ extern grub_err_t EXPORT_FUNC(grub_json_getint64) 
> (grub_int64_t *out,
>                                                  const grub_json_t *parent,
>                                                  const char *key);
>  
> +/*
> + * Unescape escaped characters and Unicode sequences in the
> + * given JSON-encoded string. Returns a newly allocated string
> + * passed back via the `out` parameter that has a length of
> + * `*outlen`.
> + *
> + * See https://datatracker.ietf.org/doc/html/rfc8259#section-7 for more
> + * information on escaping in JSON.
> + */
> +extern grub_err_t EXPORT_FUNC(grub_json_unescape) (char **out, grub_size_t 
> *outlen,
> +                                                const char *in, grub_size_t 
> inlen);
> +
>  #endif



reply via email to

[Prev in Thread] Current Thread [Next in Thread]