chiark / gitweb /
util: rework cunescape(), improve error handling
authorLennart Poettering <lennart@poettering.net>
Mon, 6 Apr 2015 18:11:41 +0000 (20:11 +0200)
committerSven Eden <yamakuzure@gmx.net>
Tue, 14 Mar 2017 06:51:14 +0000 (07:51 +0100)
Change cunescape() to return a normal error code, so that we can
distuingish OOM errors from parse errors.

This also adds a flags parameter to control whether "relaxed" or normal
parsing shall be done. If set no parse failures are generated, and the
only reason why cunescape() can fail is OOM.

src/libelogind/sd-login/sd-login.c
src/login/logind-acl.c
src/login/logind-inhibit.c
src/shared/util.c
src/shared/util.h

index 8e2b7c1dc7c239c2cdd546ab76c1713f38e0cef2..c5489917f8009a6b4471de5d3c77c8834f8fc642 100644 (file)
@@ -496,9 +496,9 @@ _public_ int sd_session_get_desktop(const char *session, char **desktop) {
         if (r < 0)
                 return r;
 
         if (r < 0)
                 return r;
 
-        t = cunescape(escaped);
-        if (!t)
-                return -ENOMEM;
+        r = cunescape(escaped, 0, &t);
+        if (r < 0)
+                return r;
 
         *desktop = t;
         return 0;
 
         *desktop = t;
         return 0;
index 941fd724a56e8a43c799884d4f9d2e65fa0c6613..d2b3337788920cb7a25507daed69ada64170a4a2 100644 (file)
@@ -253,8 +253,7 @@ int devnode_acl_all(struct udev *udev,
                 FOREACH_DIRENT(dent, dir, return -errno) {
                         _cleanup_free_ char *unescaped_devname = NULL;
 
                 FOREACH_DIRENT(dent, dir, return -errno) {
                         _cleanup_free_ char *unescaped_devname = NULL;
 
-                        unescaped_devname = cunescape(dent->d_name);
-                        if (!unescaped_devname)
+                        if (cunescape(dent->d_name, UNESCAPE_RELAX, &unescaped_devname) < 0)
                                 return -ENOMEM;
 
                         n = strappend("/dev/", unescaped_devname);
                                 return -ENOMEM;
 
                         n = strappend("/dev/", unescaped_devname);
index 5d81693e6c0bdbd4e2b03f66ca3ac05f06553fec..5eb1a2ea65f61c003298c3c1e000a0d20f5a4e23 100644 (file)
@@ -231,18 +231,18 @@ int inhibitor_load(Inhibitor *i) {
         }
 
         if (who) {
         }
 
         if (who) {
-                cc = cunescape(who);
-                if (!cc)
-                        return -ENOMEM;
+                r = cunescape(who, 0, &cc);
+                if (r < 0)
+                        return r;
 
                 free(i->who);
                 i->who = cc;
         }
 
         if (why) {
 
                 free(i->who);
                 i->who = cc;
         }
 
         if (why) {
-                cc = cunescape(why);
-                if (!cc)
-                        return -ENOMEM;
+                r = cunescape(why, 0, &cc);
+                if (r < 0)
+                        return r;
 
                 free(i->why);
                 i->why = cc;
 
                 free(i->why);
                 i->why = cc;
index 973f1070b8a1178ee4796a03ecdca2872f3cf5af..a8e485cc9c805f9647417fc23bbcf692cfc60c8a 100644 (file)
@@ -1487,12 +1487,13 @@ static int cunescape_one(const char *p, size_t length, char *ret) {
         return r;
 }
 
         return r;
 }
 
-char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix) {
+int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
         char *r, *t;
         const char *f;
         size_t pl;
 
         assert(s);
         char *r, *t;
         const char *f;
         size_t pl;
 
         assert(s);
+        assert(ret);
 
         /* Undoes C style string escaping, and optionally prefixes it. */
 
 
         /* Undoes C style string escaping, and optionally prefixes it. */
 
@@ -1500,7 +1501,7 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre
 
         r = new(char, pl+length+1);
         if (!r)
 
         r = new(char, pl+length+1);
         if (!r)
-                return NULL;
+                return -ENOMEM;
 
         if (prefix)
                 memcpy(r, prefix, pl);
 
         if (prefix)
                 memcpy(r, prefix, pl);
@@ -1512,17 +1513,31 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre
                 remaining = s + length - f;
                 assert(remaining > 0);
 
                 remaining = s + length - f;
                 assert(remaining > 0);
 
-                if (*f != '\\' || remaining == 1) {
-                        /* a literal literal, or a trailing backslash, copy verbatim */
+                if (*f != '\\') {
+                        /* A literal literal, copy verbatim */
                         *(t++) = *f;
                         continue;
                 }
 
                         *(t++) = *f;
                         continue;
                 }
 
+                if (remaining == 1) {
+                        if (flags & UNESCAPE_RELAX) {
+                                /* A trailing backslash, copy verbatim */
+                                *(t++) = *f;
+                                continue;
+                        }
+
+                        return -EINVAL;
+                }
+
                 k = cunescape_one(f + 1, remaining - 1, t);
                 if (k < 0) {
                 k = cunescape_one(f + 1, remaining - 1, t);
                 if (k < 0) {
-                        /* Invalid escape code, let's take it literal then */
-                        *(t++) = '\\';
-                        continue;
+                        if (flags & UNESCAPE_RELAX) {
+                                /* Invalid escape code, let's take it literal then */
+                                *(t++) = '\\';
+                                continue;
+                        }
+
+                        return k;
                 }
 
                 f += k;
                 }
 
                 f += k;
@@ -1530,17 +1545,17 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre
         }
 
         *t = 0;
         }
 
         *t = 0;
-        return r;
-}
 
 
-char *cunescape_length(const char *s, size_t length) {
-        return cunescape_length_with_prefix(s, length, NULL);
+        *ret = r;
+        return t - r;
 }
 
 }
 
-char *cunescape(const char *s) {
-        assert(s);
+int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) {
+        return cunescape_length_with_prefix(s, length, NULL, flags, ret);
+}
 
 
-        return cunescape_length(s, strlen(s));
+int cunescape(const char *s, UnescapeFlags flags, char **ret) {
+        return cunescape_length(s, strlen(s), flags, ret);
 }
 
 char *xescape(const char *s, const char *bad) {
 }
 
 char *xescape(const char *s, const char *bad) {
@@ -6752,9 +6767,9 @@ int umount_recursive(const char *prefix, int flags) {
                                 continue;
                         }
 
                                 continue;
                         }
 
-                        p = cunescape(path);
-                        if (!p)
-                                return -ENOMEM;
+                        r = cunescape(path, UNESCAPE_RELAX, &p);
+                        if (r < 0)
+                                return r;
 
                         if (!path_startswith(p, prefix))
                                 continue;
 
                         if (!path_startswith(p, prefix))
                                 continue;
@@ -6854,9 +6869,9 @@ int bind_remount_recursive(const char *prefix, bool ro) {
                                 continue;
                         }
 
                                 continue;
                         }
 
-                        p = cunescape(path);
-                        if (!p)
-                                return -ENOMEM;
+                        r = cunescape(path, UNESCAPE_RELAX, &p);
+                        if (r < 0)
+                                return r;
 
                         /* Let's ignore autofs mounts.  If they aren't
                          * triggered yet, we want to avoid triggering
 
                         /* Let's ignore autofs mounts.  If they aren't
                          * triggered yet, we want to avoid triggering
index 9f0149e1c5a39bf63e43b582e2af394b43be8995..2154623afd47cd243c6321cf8431576d2a84efdc 100644 (file)
@@ -312,9 +312,14 @@ char decchar(int x) _const_;
 int undecchar(char c) _const_;
 
 char *cescape(const char *s);
 int undecchar(char c) _const_;
 
 char *cescape(const char *s);
-char *cunescape(const char *s);
-char *cunescape_length(const char *s, size_t length);
-char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix);
+
+typedef enum UnescapeFlags {
+        UNESCAPE_RELAX = 1,
+} UnescapeFlags;
+
+int cunescape(const char *s, UnescapeFlags flags, char **ret);
+int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);
+int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret);
 
 char *xescape(const char *s, const char *bad);
 
 
 char *xescape(const char *s, const char *bad);
 
@@ -1015,7 +1020,7 @@ int take_password_lock(const char *root);
 int is_symlink(const char *path);
 int is_dir(const char *path, bool follow);
 
 int is_symlink(const char *path);
 int is_dir(const char *path, bool follow);
 
-typedef enum UnquoteFlags{
+typedef enum UnquoteFlags {
         UNQUOTE_RELAX     = 1,
         UNQUOTE_CUNESCAPE = 2,
 } UnquoteFlags;
         UNQUOTE_RELAX     = 1,
         UNQUOTE_CUNESCAPE = 2,
 } UnquoteFlags;