mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-08 09:02:55 +00:00
git_buf_quote: quote ugly characters
This commit is contained in:
parent
72806f4cca
commit
d3d95d5ae2
66
src/buffer.c
66
src/buffer.c
@ -858,6 +858,72 @@ int git_buf_splice(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Quote per http://marc.info/?l=git&m=112927316408690&w=2 */
|
||||
int git_buf_quote(git_buf *buf)
|
||||
{
|
||||
const char whitespace[] = { 'a', 'b', 't', 'n', 'v', 'f', 'r' };
|
||||
git_buf quoted = GIT_BUF_INIT;
|
||||
size_t i = 0;
|
||||
bool quote = false;
|
||||
int error = 0;
|
||||
|
||||
/* walk to the first char that needs quoting */
|
||||
if (buf->size && buf->ptr[0] == '!')
|
||||
quote = true;
|
||||
|
||||
for (i = 0; !quote && i < buf->size; i++) {
|
||||
if (buf->ptr[i] == '"' || buf->ptr[i] == '\\' ||
|
||||
buf->ptr[i] < ' ' || buf->ptr[i] > '~') {
|
||||
quote = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!quote)
|
||||
goto done;
|
||||
|
||||
git_buf_putc("ed, '"');
|
||||
git_buf_put("ed, buf->ptr, i);
|
||||
|
||||
for (; i < buf->size; i++) {
|
||||
/* whitespace - use the map above, which is ordered by ascii value */
|
||||
if (buf->ptr[i] >= '\a' && buf->ptr[i] <= '\r') {
|
||||
git_buf_putc("ed, '\\');
|
||||
git_buf_putc("ed, whitespace[buf->ptr[i] - '\a']);
|
||||
}
|
||||
|
||||
/* double quote and backslash must be escaped */
|
||||
else if (buf->ptr[i] == '"' || buf->ptr[i] == '\\') {
|
||||
git_buf_putc("ed, '\\');
|
||||
git_buf_putc("ed, buf->ptr[i]);
|
||||
}
|
||||
|
||||
/* escape anything unprintable as octal */
|
||||
else if (buf->ptr[i] != ' ' &&
|
||||
(buf->ptr[i] < '!' || buf->ptr[i] > '~')) {
|
||||
git_buf_printf("ed, "\\%03o", buf->ptr[i]);
|
||||
}
|
||||
|
||||
/* yay, printable! */
|
||||
else {
|
||||
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_free("ed);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Unquote per http://marc.info/?l=git&m=112927316408690&w=2 */
|
||||
int git_buf_unquote(git_buf *buf)
|
||||
{
|
||||
|
@ -173,9 +173,10 @@ void git_buf_rtrim(git_buf *buf);
|
||||
|
||||
int git_buf_cmp(const git_buf *a, const git_buf *b);
|
||||
|
||||
/* Unquote a buffer as specified in
|
||||
/* Quote and unquote a buffer as specified in
|
||||
* http://marc.info/?l=git&m=112927316408690&w=2
|
||||
*/
|
||||
int git_buf_quote(git_buf *buf);
|
||||
int git_buf_unquote(git_buf *buf);
|
||||
|
||||
/* Write data as base64 encoded in buffer */
|
||||
|
@ -1,7 +1,33 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "buffer.h"
|
||||
|
||||
static void expect_pass(const char *expected, const char *quoted)
|
||||
static void expect_quote_pass(const char *expected, const char *str)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
cl_git_pass(git_buf_puts(&buf, str));
|
||||
cl_git_pass(git_buf_quote(&buf));
|
||||
|
||||
cl_assert_equal_s(expected, git_buf_cstr(&buf));
|
||||
cl_assert_equal_i(strlen(expected), git_buf_len(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_buf_quote__quote_succeeds(void)
|
||||
{
|
||||
expect_quote_pass("", "");
|
||||
expect_quote_pass("foo", "foo");
|
||||
expect_quote_pass("foo/bar/baz.c", "foo/bar/baz.c");
|
||||
expect_quote_pass("foo bar", "foo bar");
|
||||
expect_quote_pass("\"\\\"leading quote\"", "\"leading quote");
|
||||
expect_quote_pass("\"slash\\\\y\"", "slash\\y");
|
||||
expect_quote_pass("\"foo\\r\\nbar\"", "foo\r\nbar");
|
||||
expect_quote_pass("\"foo\\177bar\"", "foo\177bar");
|
||||
expect_quote_pass("\"foo\\001bar\"", "foo\001bar");
|
||||
}
|
||||
|
||||
static void expect_unquote_pass(const char *expected, const char *quoted)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
@ -14,7 +40,7 @@ static void expect_pass(const char *expected, const char *quoted)
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
static void expect_fail(const char *quoted)
|
||||
static void expect_unquote_fail(const char *quoted)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
@ -26,32 +52,32 @@ static void expect_fail(const char *quoted)
|
||||
|
||||
void test_buf_quote__unquote_succeeds(void)
|
||||
{
|
||||
expect_pass("", "\"\"");
|
||||
expect_pass(" ", "\" \"");
|
||||
expect_pass("foo", "\"foo\"");
|
||||
expect_pass("foo bar", "\"foo bar\"");
|
||||
expect_pass("foo\"bar", "\"foo\\\"bar\"");
|
||||
expect_pass("foo\\bar", "\"foo\\\\bar\"");
|
||||
expect_pass("foo\tbar", "\"foo\\tbar\"");
|
||||
expect_pass("\vfoo\tbar\n", "\"\\vfoo\\tbar\\n\"");
|
||||
expect_pass("foo\nbar", "\"foo\\012bar\"");
|
||||
expect_pass("foo\r\nbar", "\"foo\\015\\012bar\"");
|
||||
expect_pass("foo\r\nbar", "\"\\146\\157\\157\\015\\012\\142\\141\\162\"");
|
||||
expect_pass("newline: \n", "\"newline: \\012\"");
|
||||
expect_unquote_pass("", "\"\"");
|
||||
expect_unquote_pass(" ", "\" \"");
|
||||
expect_unquote_pass("foo", "\"foo\"");
|
||||
expect_unquote_pass("foo bar", "\"foo bar\"");
|
||||
expect_unquote_pass("foo\"bar", "\"foo\\\"bar\"");
|
||||
expect_unquote_pass("foo\\bar", "\"foo\\\\bar\"");
|
||||
expect_unquote_pass("foo\tbar", "\"foo\\tbar\"");
|
||||
expect_unquote_pass("\vfoo\tbar\n", "\"\\vfoo\\tbar\\n\"");
|
||||
expect_unquote_pass("foo\nbar", "\"foo\\012bar\"");
|
||||
expect_unquote_pass("foo\r\nbar", "\"foo\\015\\012bar\"");
|
||||
expect_unquote_pass("foo\r\nbar", "\"\\146\\157\\157\\015\\012\\142\\141\\162\"");
|
||||
expect_unquote_pass("newline: \n", "\"newline: \\012\"");
|
||||
}
|
||||
|
||||
void test_buf_quote__unquote_fails(void)
|
||||
{
|
||||
expect_fail("no quotes at all");
|
||||
expect_fail("\"no trailing quote");
|
||||
expect_fail("no leading quote\"");
|
||||
expect_fail("\"invalid \\z escape char\"");
|
||||
expect_fail("\"\\q invalid escape char\"");
|
||||
expect_fail("\"invalid escape char \\p\"");
|
||||
expect_fail("\"invalid \\1 escape char \"");
|
||||
expect_fail("\"invalid \\14 escape char \"");
|
||||
expect_fail("\"invalid \\411 escape char\"");
|
||||
expect_fail("\"truncated escape char \\\"");
|
||||
expect_fail("\"truncated escape char \\0\"");
|
||||
expect_fail("\"truncated escape char \\01\"");
|
||||
expect_unquote_fail("no quotes at all");
|
||||
expect_unquote_fail("\"no trailing quote");
|
||||
expect_unquote_fail("no leading quote\"");
|
||||
expect_unquote_fail("\"invalid \\z escape char\"");
|
||||
expect_unquote_fail("\"\\q invalid escape char\"");
|
||||
expect_unquote_fail("\"invalid escape char \\p\"");
|
||||
expect_unquote_fail("\"invalid \\1 escape char \"");
|
||||
expect_unquote_fail("\"invalid \\14 escape char \"");
|
||||
expect_unquote_fail("\"invalid \\411 escape char\"");
|
||||
expect_unquote_fail("\"truncated escape char \\\"");
|
||||
expect_unquote_fail("\"truncated escape char \\0\"");
|
||||
expect_unquote_fail("\"truncated escape char \\01\"");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user