diff options
author | Ronan Pigott <ronan@rjp.ie> | 2024-01-04 02:53:28 +0100 |
---|---|---|
committer | Ronan Pigott <ronan@rjp.ie> | 2024-01-16 18:49:26 +0100 |
commit | b699f5f2cdb89d7def80097419ee2054f54ed5da (patch) | |
tree | 7596c57b072cfdce9937ae347030f43ad02c713a | |
parent | resolved: enable RFC9460 SVCB and HTTPS records (diff) | |
download | systemd-b699f5f2cdb89d7def80097419ee2054f54ed5da.tar.xz systemd-b699f5f2cdb89d7def80097419ee2054f54ed5da.zip |
escape: introduce decescape
This 3-digit decimal escape style is useful when presenting DNS RR
information in zone-file presentation format.
-rw-r--r-- | src/basic/escape.c | 27 | ||||
-rw-r--r-- | src/basic/escape.h | 1 | ||||
-rw-r--r-- | src/test/test-escape.c | 18 |
3 files changed, 46 insertions, 0 deletions
diff --git a/src/basic/escape.c b/src/basic/escape.c index 75a1d68e96..d95f35e798 100644 --- a/src/basic/escape.c +++ b/src/basic/escape.c @@ -471,6 +471,33 @@ char* octescape(const char *s, size_t len) { return buf; } +char* decescape(const char *s, const char *bad, size_t len) { + char *buf, *t; + + /* Escapes all chars in bad, in addition to \ and " chars, in \nnn decimal style escaping. */ + + assert(s || len == 0); + + t = buf = new(char, len * 4 + 1); + if (!buf) + return NULL; + + for (size_t i = 0; i < len; i++) { + uint8_t u = (uint8_t) s[i]; + + if (u < ' ' || u >= 127 || IN_SET(u, '\\', '"') || strchr(bad, u)) { + *(t++) = '\\'; + *(t++) = '0' + (u / 100); + *(t++) = '0' + ((u / 10) % 10); + *(t++) = '0' + (u % 10); + } else + *(t++) = u; + } + + *t = 0; + return buf; +} + static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad) { assert(bad); assert(t); diff --git a/src/basic/escape.h b/src/basic/escape.h index 318da6f220..65caf0dbcf 100644 --- a/src/basic/escape.h +++ b/src/basic/escape.h @@ -65,6 +65,7 @@ static inline char* xescape(const char *s, const char *bad) { return xescape_full(s, bad, SIZE_MAX, 0); } char* octescape(const char *s, size_t len); +char* decescape(const char *s, const char *bad, size_t len); char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFlags flags); char* shell_escape(const char *s, const char *bad); diff --git a/src/test/test-escape.c b/src/test/test-escape.c index 21786ae72a..364e0f3956 100644 --- a/src/test/test-escape.c +++ b/src/test/test-escape.c @@ -239,4 +239,22 @@ TEST(octescape) { test_octescape_one("\123\213\222", "\123\\213\\222"); } +static void test_decescape_one(const char *s, const char *bad, const char *expected) { + _cleanup_free_ char *ret = NULL; + + assert_se(ret = decescape(s, bad, strlen_ptr(s))); + log_debug("decescape(\"%s\") → \"%s\" (expected: \"%s\")", strnull(s), ret, expected); + assert_se(streq(ret, expected)); +} + +TEST(decescape) { + test_decescape_one(NULL, "bad", ""); + test_decescape_one("foo", "", "foo"); + test_decescape_one("foo", "f", "\\102oo"); + test_decescape_one("foo", "o", "f\\111\\111"); + test_decescape_one("go\"bb\\ledyg\x03ook\r\n", "", "go\\034bb\\092ledyg\\003ook\\013\\010"); + test_decescape_one("\\xff\xff" "f", "f", "\\092x\\102\\102\\255\\102"); + test_decescape_one("all", "all", "\\097\\108\\108"); +} + DEFINE_TEST_MAIN(LOG_DEBUG); |