]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
escape: introduce decescape
authorRonan Pigott <ronan@rjp.ie>
Thu, 4 Jan 2024 01:53:28 +0000 (18:53 -0700)
committerRonan Pigott <ronan@rjp.ie>
Tue, 16 Jan 2024 17:49:26 +0000 (10:49 -0700)
This 3-digit decimal escape style is useful when presenting DNS RR
information in zone-file presentation format.

src/basic/escape.c
src/basic/escape.h
src/test/test-escape.c

index 75a1d68e967254a73b5ffdde951fb2ffd2798241..d95f35e79807ff470c808837996bc702179205be 100644 (file)
@@ -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);
index 318da6f220347fb6cb1a880a80e64371c07cb1f4..65caf0dbcfa3b1660fdfadd500115ad8a1850f9b 100644 (file)
@@ -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);
index 21786ae72aaa856cbeb07632ab444643da6cdfcd..364e0f395643ab54c7937b0cf5013ad2007fbe96 100644 (file)
@@ -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);