From: ZheNing Hu <adlternative@xxxxxxxxx> With the original functions `*._quote_buf()`, there may be '\0' in our source string, only the content before the first '\0' will be processed and added to the buffer. Add `perl_quote_buf_with_size()`, `python_quote_buf_with_size()`, `tcl_quote_buf_with_size`,`sq_quote_buf_with_size()` to `quote.c`, they will process the source string with specified length characters. With them, the content after '\0' will not be truncated. This will help us add binary data containing '\0' to `quote_formatting()` in `ref-filter.c`. Signed-off-by: ZheNing Hu <adlternative@xxxxxxxxx> --- quote.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ quote.h | 4 ++ 2 files changed, 120 insertions(+) diff --git a/quote.c b/quote.c index 8a3a5e39eb12..9a1d9dde1fdb 100644 --- a/quote.c +++ b/quote.c @@ -43,6 +43,39 @@ void sq_quote_buf(struct strbuf *dst, const char *src) free(to_free); } +void sq_quote_buf_with_size(struct strbuf *dst, const char *src, size_t size) +{ + char *to_free = NULL; + size_t cur_size = 0; + + if (dst->buf == src) + to_free = strbuf_detach(dst, NULL); + + strbuf_addch(dst, '\''); + while (cur_size < size) { + size_t len = strcspn(src, "'!"); + if (!len) { + strbuf_add(dst, src, 1); + src++; + cur_size++; + } else { + strbuf_add(dst, src, len); + src += len; + cur_size += len; + } + if (cur_size >= size) + break; + while (need_bs_quote(*src)) { + strbuf_addstr(dst, "'\\"); + strbuf_addch(dst, *src++); + cur_size++; + strbuf_addch(dst, '\''); + } + } + strbuf_addch(dst, '\''); + free(to_free); +} + void sq_quote_buf_pretty(struct strbuf *dst, const char *src) { static const char ok_punct[] = "+,-./:=@_^"; @@ -471,6 +504,25 @@ void perl_quote_buf(struct strbuf *sb, const char *src) strbuf_addch(sb, sq); } +void perl_quote_buf_with_size(struct strbuf *sb, const char *src, size_t size) +{ + const char sq = '\''; + const char bq = '\\'; + char c; + size_t cur_size = 0; + + strbuf_addch(sb, sq); + while (cur_size < size) { + c = *src++; + cur_size++; + + if (c == sq || c == bq) + strbuf_addch(sb, bq); + strbuf_addch(sb, c); + } + strbuf_addch(sb, sq); +} + void python_quote_buf(struct strbuf *sb, const char *src) { const char sq = '\''; @@ -492,6 +544,31 @@ void python_quote_buf(struct strbuf *sb, const char *src) strbuf_addch(sb, sq); } +void python_quote_buf_with_size(struct strbuf *sb, const char *src, size_t size) +{ + const char sq = '\''; + const char bq = '\\'; + const char nl = '\n'; + char c; + size_t cur_size = 0; + + strbuf_addch(sb, sq); + while (cur_size < size) { + c = *src++; + cur_size++; + + if (c == nl) { + strbuf_addch(sb, bq); + strbuf_addch(sb, 'n'); + continue; + } + if (c == sq || c == bq) + strbuf_addch(sb, bq); + strbuf_addch(sb, c); + } + strbuf_addch(sb, sq); +} + void tcl_quote_buf(struct strbuf *sb, const char *src) { char c; @@ -527,6 +604,45 @@ void tcl_quote_buf(struct strbuf *sb, const char *src) strbuf_addch(sb, '"'); } +void tcl_quote_buf_with_size(struct strbuf *sb, const char *src, size_t size) +{ + char c; + size_t cur_size = 0; + + strbuf_addch(sb, '"'); + while (cur_size < size) { + c = *src++; + cur_size++; + + switch (c) { + case '[': case ']': + case '{': case '}': + case '$': case '\\': case '"': + strbuf_addch(sb, '\\'); + /* fallthrough */ + default: + strbuf_addch(sb, c); + break; + case '\f': + strbuf_addstr(sb, "\\f"); + break; + case '\r': + strbuf_addstr(sb, "\\r"); + break; + case '\n': + strbuf_addstr(sb, "\\n"); + break; + case '\t': + strbuf_addstr(sb, "\\t"); + break; + case '\v': + strbuf_addstr(sb, "\\v"); + break; + } + } + strbuf_addch(sb, '"'); +} + void basic_regex_quote_buf(struct strbuf *sb, const char *src) { char c; diff --git a/quote.h b/quote.h index 768cc6338e27..e894507329cc 100644 --- a/quote.h +++ b/quote.h @@ -30,6 +30,7 @@ struct strbuf; */ void sq_quote_buf(struct strbuf *, const char *src); +void sq_quote_buf_with_size(struct strbuf *, const char *src, size_t size); void sq_quote_argv(struct strbuf *, const char **argv); void sq_quotef(struct strbuf *, const char *fmt, ...); @@ -94,8 +95,11 @@ char *quote_path(const char *in, const char *prefix, struct strbuf *out, unsigne /* quoting as a string literal for other languages */ void perl_quote_buf(struct strbuf *sb, const char *src); +void perl_quote_buf_with_size(struct strbuf *sb, const char *src, size_t size); void python_quote_buf(struct strbuf *sb, const char *src); +void python_quote_buf_with_size(struct strbuf *sb, const char *src, size_t size); void tcl_quote_buf(struct strbuf *sb, const char *src); +void tcl_quote_buf_with_size(struct strbuf *sb, const char *src, size_t size); void basic_regex_quote_buf(struct strbuf *sb, const char *src); #endif -- gitgitgadget