aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2018-07-02 18:24:10 +0000
committerWerner Koch <[email protected]>2018-07-02 18:25:30 +0000
commit58baf40af641f8cbf597e508a292e85ae94688f1 (patch)
tree4220db56a47ede8a3f6853706014e1ca2f992209
parentagent: Fix segv running in --server mode (diff)
downloadgnupg-58baf40af641f8cbf597e508a292e85ae94688f1.tar.gz
gnupg-58baf40af641f8cbf597e508a292e85ae94688f1.zip
common: New function percent_data_escape.
* common/percent.c (percent_data_escape): New. * common/t-percent.c (test_percent_data_escape): New. Signed-off-by: Werner Koch <[email protected]>
-rw-r--r--common/percent.c44
-rw-r--r--common/t-percent.c51
-rw-r--r--common/util.h1
3 files changed, 95 insertions, 1 deletions
diff --git a/common/percent.c b/common/percent.c
index 569c5fd99..eeb026fbe 100644
--- a/common/percent.c
+++ b/common/percent.c
@@ -87,6 +87,50 @@ percent_plus_escape (const char *string)
}
+/* Create a newly alloced string from (DATA,DATALEN) with embedded
+ * Nuls quoted as %00. The standard percent unescaping can be
+ * used to reverse this encoding. */
+char *
+percent_data_escape (const void *data, size_t datalen)
+{
+ char *buffer, *p;
+ const char *s;
+ size_t n, length;
+
+ for (length=1, s=data, n=datalen; n; s++, n--)
+ {
+ if (!*s || *s == '%')
+ length += 3;
+ else
+ length++;
+ }
+
+ buffer = p = xtrymalloc (length);
+ if (!buffer)
+ return NULL;
+
+ for (s=data, n=datalen; n; s++, n--)
+ {
+ if (!*s)
+ {
+ memcpy (p, "%00", 3);
+ p += 3;
+ }
+ else if (*s == '%')
+ {
+ memcpy (p, "%25", 3);
+ p += 3;
+ }
+ else
+ *p++ = *s;
+ }
+ *p = 0;
+
+ return buffer;
+
+}
+
+
/* Do the percent and plus/space unescaping from STRING to BUFFER and
return the length of the valid buffer. Plus unescaping is only
done if WITHPLUS is true. An escaped Nul character will be
diff --git a/common/t-percent.c b/common/t-percent.c
index 145a89bf3..94ece9249 100644
--- a/common/t-percent.c
+++ b/common/t-percent.c
@@ -99,6 +99,55 @@ test_percent_plus_escape (void)
}
+static void
+test_percent_data_escape (void)
+{
+ static struct {
+ const char *data;
+ size_t datalen;
+ const char *expect;
+ } tbl[] = {
+ {
+ "", 0,
+ ""
+ }, {
+ "a", 1,
+ "a",
+ }, {
+ "%22", 3,
+ "%2522"
+ }, {
+ "%%", 3,
+ "%25%25%00"
+ }, {
+ "\n \0BC\t", 6,
+ "\n %00BC\t"
+ }, { NULL, 0, NULL }
+ };
+ char *buf;
+ int i;
+ size_t len;
+
+ for (i=0; tbl[i].data; i++)
+ {
+ buf = percent_data_escape (tbl[i].data, tbl[i].datalen);
+ if (!buf)
+ {
+ fprintf (stderr, "out of core: %s\n", strerror (errno));
+ exit (2);
+ }
+ if (strcmp (buf, tbl[i].expect))
+ fail (i);
+ len = percent_plus_unescape_inplace (buf, 0);
+ if (len != tbl[i].datalen)
+ fail (i);
+ else if (memcmp (buf, tbl[i].data, tbl[i].datalen))
+ fail (i);
+ xfree (buf);
+ }
+}
+
+
int
main (int argc, char **argv)
@@ -109,6 +158,6 @@ main (int argc, char **argv)
/* FIXME: We escape_unescape is not tested - only
percent_plus_unescape. */
test_percent_plus_escape ();
-
+ test_percent_data_escape ();
return 0;
}
diff --git a/common/util.h b/common/util.h
index 123d88079..682415d92 100644
--- a/common/util.h
+++ b/common/util.h
@@ -201,6 +201,7 @@ char *hex2str_alloc (const char *hexstring, size_t *r_count);
/*-- percent.c --*/
char *percent_plus_escape (const char *string);
+char *percent_data_escape (const void *data, size_t datalen);
char *percent_plus_unescape (const char *string, int nulrepl);
char *percent_unescape (const char *string, int nulrepl);