On Mon, 6 Jun 2022 07:28:56 +0200 Patrick Steinhardt <p...@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 <p...@pks.im> Reviewed-by: Glenn Washburn <developm...@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 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel