diff options
-rw-r--r-- | src/shared/util.c | 33 | ||||
-rw-r--r-- | src/test/test-util.c | 20 |
2 files changed, 37 insertions, 16 deletions
diff --git a/src/shared/util.c b/src/shared/util.c index 280e42b305..1210900bca 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -1352,12 +1352,19 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre memcpy(r, prefix, pl); for (f = s, t = r + pl; f < s + length; f++) { + size_t remaining = s + length - f; + assert(remaining > 0); - if (*f != '\\') { + if (*f != '\\') { /* a literal literal */ *(t++) = *f; continue; } + if (--remaining == 0) { /* copy trailing backslash verbatim */ + *(t++) = *f; + break; + } + f++; switch (*f) { @@ -1400,10 +1407,12 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre case 'x': { /* hexadecimal encoding */ - int a, b; + int a = -1, b = -1; - a = unhexchar(f[1]); - b = unhexchar(f[2]); + if (remaining >= 2) { + a = unhexchar(f[1]); + b = unhexchar(f[2]); + } if (a < 0 || b < 0 || (a == 0 && b == 0)) { /* Invalid escape code, let's take it literal then */ @@ -1426,11 +1435,13 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre case '6': case '7': { /* octal encoding */ - int a, b, c; + int a = -1, b = -1, c = -1; - a = unoctchar(f[0]); - b = unoctchar(f[1]); - c = unoctchar(f[2]); + if (remaining >= 3) { + a = unoctchar(f[0]); + b = unoctchar(f[1]); + c = unoctchar(f[2]); + } if (a < 0 || b < 0 || c < 0 || (a == 0 && b == 0 && c == 0)) { /* Invalid escape code, let's take it literal then */ @@ -1444,11 +1455,6 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre break; } - case 0: - /* premature end of string. */ - *(t++) = '\\'; - goto finish; - default: /* Invalid escape code, let's take it literal then */ *(t++) = '\\'; @@ -1457,7 +1463,6 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre } } -finish: *t = 0; return r; } diff --git a/src/test/test-util.c b/src/test/test-util.c index 1e50a29f79..4bb51545be 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -416,8 +416,24 @@ static void test_cescape(void) { static void test_cunescape(void) { _cleanup_free_ char *unescaped; - assert_se(unescaped = cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00")); - assert_se(streq(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00")); + unescaped = cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00"); + assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00")); + + /* incomplete sequences */ + unescaped = cunescape("\\x0"); + assert_se(streq_ptr(unescaped, "\\x0")); + + unescaped = cunescape("\\x"); + assert_se(streq_ptr(unescaped, "\\x")); + + unescaped = cunescape("\\"); + assert_se(streq_ptr(unescaped, "\\")); + + unescaped = cunescape("\\11"); + assert_se(streq_ptr(unescaped, "\\11")); + + unescaped = cunescape("\\1"); + assert_se(streq_ptr(unescaped, "\\1")); } static void test_foreach_word(void) { |