]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
escape: introduce UNESCAPE_ACCEPT_NUL flag
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 27 Jan 2020 08:46:22 +0000 (17:46 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 27 Jan 2020 09:04:46 +0000 (18:04 +0900)
src/basic/escape.c
src/basic/escape.h
src/basic/extract-word.c

index a0b0a771090b7e5f4da5015ecd880d1194f49308..c5c44d2e7d8e940b087edf28e10e7c69031745e8 100644 (file)
@@ -102,7 +102,7 @@ char *cescape(const char *s) {
         return cescape_length(s, strlen(s));
 }
 
-int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) {
+int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit, bool accept_nul) {
         int r = 1;
 
         assert(p);
@@ -171,7 +171,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
                         return -EINVAL;
 
                 /* Don't allow NUL bytes */
-                if (a == 0 && b == 0)
+                if (a == 0 && b == 0 && !accept_nul)
                         return -EINVAL;
 
                 *ret = (a << 4U) | b;
@@ -199,7 +199,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
                 c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
 
                 /* Don't allow 0 chars */
-                if (c == 0)
+                if (c == 0 && !accept_nul)
                         return -EINVAL;
 
                 *ret = c;
@@ -227,7 +227,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
                     ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] <<  8U) | ((uint32_t) a[6] <<  4U) |  (uint32_t) a[7];
 
                 /* Don't allow 0 chars */
-                if (c == 0)
+                if (c == 0 && !accept_nul)
                         return -EINVAL;
 
                 /* Don't allow invalid code points */
@@ -267,7 +267,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
                         return -EINVAL;
 
                 /* don't allow NUL bytes */
-                if (a == 0 && b == 0 && c == 0)
+                if (a == 0 && b == 0 && c == 0 && !accept_nul)
                         return -EINVAL;
 
                 /* Don't allow bytes above 255 */
@@ -333,7 +333,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
                         return -EINVAL;
                 }
 
-                k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit);
+                k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit, flags & UNESCAPE_ACCEPT_NUL);
                 if (k < 0) {
                         if (flags & UNESCAPE_RELAX) {
                                 /* Invalid escape code, let's take it literal then */
index dfd10f93154c417b29ffe7b48a76410a369671fe..b8eb137c3d398bf4e6adf48c33d3f7721eaac7d4 100644 (file)
 #define SHELL_NEED_ESCAPE_POSIX "\\\'"
 
 typedef enum UnescapeFlags {
-        UNESCAPE_RELAX = 1,
+        UNESCAPE_RELAX      = 1 << 0,
+        UNESCAPE_ACCEPT_NUL = 1 << 1,
 } UnescapeFlags;
 
 typedef enum EscapeStyle {
         ESCAPE_BACKSLASH = 1,
-        ESCAPE_POSIX = 2,
+        ESCAPE_POSIX     = 2,
 } EscapeStyle;
 
 char *cescape(const char *s);
@@ -48,7 +49,7 @@ static inline int cunescape_length(const char *s, size_t length, UnescapeFlags f
 static inline int cunescape(const char *s, UnescapeFlags flags, char **ret) {
         return cunescape_length(s, strlen(s), flags, ret);
 }
-int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
+int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit, bool accept_nul);
 
 char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits);
 static inline char *xescape(const char *s, const char *bad) {
index d7c215cb48e7a267e4bc5f3e2f28d19d62aaeec9..ac9bf6099d87f62a78f9d9f9c7d01475db97121e 100644 (file)
@@ -90,7 +90,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                                 bool eight_bit = false;
                                 char32_t u;
 
-                                r = cunescape_one(*p, (size_t) -1, &u, &eight_bit);
+                                r = cunescape_one(*p, (size_t) -1, &u, &eight_bit, false);
                                 if (r < 0) {
                                         if (flags & EXTRACT_CUNESCAPE_RELAX) {
                                                 s[sz++] = '\\';