diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2020-04-02 11:39:54 +0100 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2020-06-05 07:14:26 +0100 |
commit | 2cd125280281220b0dc429215a99157f5fef89de (patch) | |
tree | 9ef1e65ce64d30e0e984fd3411c364e9c1f07a56 | |
parent | 8a81cfb53ce96b0fe008d8c6448b809fba7a2d51 (diff) | |
download | libgit2-2cd125280281220b0dc429215a99157f5fef89de.tar.gz |
buf: introduce git_buf_shellquote
Introduce a helper method to quote a string in a shellsafe manner. This
wraps the entire buffer in single quotes, escaping single-quotes and
exclamation points.
-rw-r--r-- | src/util/buffer.c | 37 | ||||
-rw-r--r-- | src/util/buffer.h | 6 | ||||
-rw-r--r-- | tests/libgit2/buf/basic.c | 29 |
3 files changed, 72 insertions, 0 deletions
diff --git a/src/util/buffer.c b/src/util/buffer.c index 5d84b99fc..28db5c20c 100644 --- a/src/util/buffer.c +++ b/src/util/buffer.c @@ -1155,3 +1155,40 @@ done: git_buf_dispose(&replaced); return error; } + +int git_buf_shellquote(git_buf *buf) +{ + git_buf quoted = GIT_BUF_INIT; + size_t i; + int error = 0; + + ENSURE_SIZE("ed, buf->size); + + git_buf_putc("ed, '\''); + + for (i = 0; i < buf->size; i++) { + switch (buf->ptr[i]) { + case '\'': + case '!': + git_buf_puts("ed, "'\\"); + git_buf_putc("ed, buf->ptr[i]); + git_buf_putc("ed, '\''); + break; + default: + git_buf_putc("ed, buf->ptr[i]); + } + } + + git_buf_putc("ed, '\''); + + if (git_buf_oom("ed)) { + error = -1; + goto done; + } + + git_buf_swap("ed, buf); + +done: + git_buf_dispose("ed); + return error; +} diff --git a/src/util/buffer.h b/src/util/buffer.h index bc0133465..95953082d 100644 --- a/src/util/buffer.h +++ b/src/util/buffer.h @@ -269,4 +269,10 @@ int git_buf_replace( const char *replacements[][2], size_t replacements_len); +/** + * Quote for shell safety. Wrap the given buffer in single quotes, + * escaping any single quotes and exclamation points. + */ +int git_buf_shellquote(git_buf *buf); + #endif diff --git a/tests/libgit2/buf/basic.c b/tests/libgit2/buf/basic.c index 0de860983..0cb180b7f 100644 --- a/tests/libgit2/buf/basic.c +++ b/tests/libgit2/buf/basic.c @@ -65,3 +65,32 @@ void test_buf_basic__replace(void) git_buf_dispose(&buf); } + +void test_buf_basic__shellquote(void) +{ + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_buf_puts(&buf, "filename")); + cl_git_pass(git_buf_shellquote(&buf)); + cl_assert_equal_s("\'filename\'", buf.ptr); + + git_buf_clear(&buf); + + cl_git_pass(git_buf_puts(&buf, "file name")); + cl_git_pass(git_buf_shellquote(&buf)); + cl_assert_equal_s("\'file name\'", buf.ptr); + + git_buf_clear(&buf); + + cl_git_pass(git_buf_puts(&buf, "file\'name")); + cl_git_pass(git_buf_shellquote(&buf)); + cl_assert_equal_s("\'file\'\\\'\'name\'", buf.ptr); + + git_buf_clear(&buf); + + cl_git_pass(git_buf_puts(&buf, "file!name")); + cl_git_pass(git_buf_shellquote(&buf)); + cl_assert_equal_s("\'file\'\\!\'name\'", buf.ptr); + + git_buf_dispose(&buf); +} |