Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
git-mirror
/
git
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
0
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security
Insights
Files
9a8c2b6
Documentation
block-sha1
builtin
compat
contrib
ewah
git-gui
gitk-git
gitweb
mergetools
perl
po
ppc
t
templates
vcs-svn
xdiff
.gitattributes
.gitignore
.mailmap
COPYING
GIT-VERSION-GEN
INSTALL
LGPL-2.1
Makefile
README
RelNotes
abspath.c
aclocal.m4
advice.c
advice.h
alias.c
alloc.c
archive-tar.c
archive-zip.c
archive.c
archive.h
argv-array.c
argv-array.h
attr.c
attr.h
base85.c
bisect.c
bisect.h
blob.c
blob.h
branch.c
branch.h
builtin.h
bulk-checkin.c
bulk-checkin.h
bundle.c
bundle.h
cache-tree.c
cache-tree.h
cache.h
check-builtins.sh
check-racy.c
check_bindir
color.c
color.h
column.c
column.h
combine-diff.c
command-list.txt
commit-slab.h
commit.c
commit.h
config.c
config.mak.in
config.mak.uname
configure.ac
connect.c
connect.h
connected.c
connected.h
convert.c
convert.h
copy.c
credential-cache--daemon.c
credential-cache.c
credential-store.c
credential.c
credential.h
csum-file.c
csum-file.h
ctype.c
daemon.c
date.c
decorate.c
decorate.h
delta.h
diff-delta.c
diff-lib.c
diff-no-index.c
diff.c
diff.h
diffcore-break.c
diffcore-delta.c
diffcore-order.c
diffcore-pickaxe.c
diffcore-rename.c
diffcore.h
dir.c
dir.h
editor.c
entry.c
environment.c
exec_cmd.c
exec_cmd.h
fast-import.c
fetch-pack.c
fetch-pack.h
fmt-merge-msg.h
fsck.c
fsck.h
generate-cmdlist.sh
gettext.c
gettext.h
git-add--interactive.perl
git-am.sh
git-archimport.perl
git-bisect.sh
git-compat-util.h
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-difftool--helper.sh
git-difftool.perl
git-filter-branch.sh
git-instaweb.sh
git-merge-octopus.sh
git-merge-one-file.sh
git-merge-resolve.sh
git-mergetool--lib.sh
git-mergetool.sh
git-p4.py
git-parse-remote.sh
git-pull.sh
git-quiltimport.sh
git-rebase--am.sh
git-rebase--interactive.sh
git-rebase--merge.sh
git-rebase.sh
git-relink.perl
git-remote-testgit.sh
git-request-pull.sh
git-send-email.perl
git-sh-i18n.sh
git-sh-setup.sh
git-stash.sh
git-submodule.sh
git-svn.perl
git-web--browse.sh
git.c
git.rc
git.spec.in
gpg-interface.c
gpg-interface.h
graph.c
graph.h
grep.c
grep.h
hashmap.c
hashmap.h
help.c
help.h
hex.c
http-backend.c
http-fetch.c
http-push.c
http-walker.c
http.c
http.h
ident.c
imap-send.c
khash.h
kwset.c
kwset.h
levenshtein.c
levenshtein.h
line-log.c
line-log.h
line-range.c
line-range.h
list-objects.c
list-objects.h
ll-merge.c
ll-merge.h
lockfile.c
log-tree.c
log-tree.h
mailmap.c
mailmap.h
match-trees.c
merge-blobs.c
merge-blobs.h
merge-recursive.c
merge-recursive.h
merge.c
mergesort.c
mergesort.h
name-hash.c
notes-cache.c
notes-cache.h
notes-merge.c
notes-merge.h
notes-utils.c
notes-utils.h
notes.c
notes.h
object.c
object.h
pack-bitmap-write.c
pack-bitmap.c
pack-bitmap.h
pack-check.c
pack-objects.c
pack-objects.h
pack-revindex.c
pack-revindex.h
pack-write.c
pack.h
pager.c
parse-options-cb.c
parse-options.c
parse-options.h
patch-delta.c
patch-ids.c
patch-ids.h
path.c
pathspec.c
pathspec.h
pkt-line.c
pkt-line.h
preload-index.c
pretty.c
prio-queue.c
prio-queue.h
progress.c
progress.h
prompt.c
prompt.h
quote.c
quote.h
reachable.c
reachable.h
read-cache.c
reflog-walk.c
reflog-walk.h
refs.c
refs.h
remote-curl.c
remote-testsvn.c
remote.c
remote.h
replace_object.c
rerere.c
rerere.h
resolve-undo.c
resolve-undo.h
revision.c
revision.h
run-command.c
run-command.h
send-pack.c
send-pack.h
sequencer.c
sequencer.h
server-info.c
setup.c
sh-i18n--envsubst.c
sha1-array.c
sha1-array.h
sha1-lookup.c
sha1-lookup.h
sha1_file.c
sha1_name.c
shallow.c
shell.c
shortlog.h
show-index.c
sideband.c
sideband.h
sigchain.c
sigchain.h
strbuf.c
strbuf.h
streaming.c
streaming.h
string-list.c
string-list.h
submodule.c
submodule.h
symlinks.c
tag.c
tag.h
tar.h
test-chmtime.c
test-ctype.c
test-date.c
test-delta.c
test-dump-cache-tree.c
test-genrandom.c
test-hashmap.c
test-index-version.c
test-line-buffer.c
test-match-trees.c
test-mergesort.c
test-mktemp.c
test-parse-options.c
test-path-utils.c
test-prio-queue.c
test-read-cache.c
test-regex.c
test-revision-walking.c
test-run-command.c
test-scrap-cache-tree.c
test-sha1.c
test-sha1.sh
test-sigchain.c
test-string-list.c
test-subprocess.c
test-svn-fe.c
test-urlmatch-normalization.c
test-wildmatch.c
thread-utils.c
thread-utils.h
trace.c
transport-helper.c
transport.c
transport.h
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
tree.h
unimplemented.sh
unix-socket.c
unix-socket.h
unpack-trees.c
unpack-trees.h
upload-pack.c
url.c
url.h
urlmatch.c
urlmatch.h
usage.c
userdiff.c
userdiff.h
utf8.c
utf8.h
varint.c
varint.h
version.c
version.h
versioncmp.c
walker.c
walker.h
wildmatch.c
wildmatch.h
wrap-for-bin.sh
wrapper.c
write_or_die.c
ws.c
wt-status.c
wt-status.h
xdiff-interface.c
xdiff-interface.h
zlib.c
Breadcrumbs
git
/
quote.c
Blame
Blame
Latest commit
History
History
462 lines (411 loc) · 10.2 KB
Breadcrumbs
git
/
quote.c
Top
File metadata and controls
Code
Blame
462 lines (411 loc) · 10.2 KB
Raw
#include "cache.h" #include "quote.h" #include "argv-array.h" int quote_path_fully = 1; /* Help to copy the thing properly quoted for the shell safety. * any single quote is replaced with '\'', any exclamation point * is replaced with '\!', and the whole thing is enclosed in a * * E.g. * original sq_quote result * name ==> name ==> 'name' * a b ==> a b ==> 'a b' * a'b ==> a'\''b ==> 'a'\''b' * a!b ==> a'\!'b ==> 'a'\!'b' */ static inline int need_bs_quote(char c) { return (c == '\'' || c == '!'); } void sq_quote_buf(struct strbuf *dst, const char *src) { char *to_free = NULL; if (dst->buf == src) to_free = strbuf_detach(dst, NULL); strbuf_addch(dst, '\''); while (*src) { size_t len = strcspn(src, "'!"); strbuf_add(dst, src, len); src += len; while (need_bs_quote(*src)) { strbuf_addstr(dst, "'\\"); strbuf_addch(dst, *src++); strbuf_addch(dst, '\''); } } strbuf_addch(dst, '\''); free(to_free); } void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) { int i; /* Copy into destination buffer. */ strbuf_grow(dst, 255); for (i = 0; argv[i]; ++i) { strbuf_addch(dst, ' '); sq_quote_buf(dst, argv[i]); if (maxlen && dst->len > maxlen) die("Too many or long arguments"); } } static char *sq_dequote_step(char *arg, char **next) { char *dst = arg; char *src = arg; char c; if (*src != '\'') return NULL; for (;;) { c = *++src; if (!c) return NULL; if (c != '\'') { *dst++ = c; continue; } /* We stepped out of sq */ switch (*++src) { case '\0': *dst = 0; if (next) *next = NULL; return arg; case '\\': c = *++src; if (need_bs_quote(c) && *++src == '\'') { *dst++ = c; continue; } /* Fallthrough */ default: if (!next || !isspace(*src)) return NULL; do { c = *++src; } while (isspace(c)); *dst = 0; *next = src; return arg; } } } char *sq_dequote(char *arg) { return sq_dequote_step(arg, NULL); } static int sq_dequote_to_argv_internal(char *arg, const char ***argv, int *nr, int *alloc, struct argv_array *array) { char *next = arg; if (!*arg) return 0; do { char *dequoted = sq_dequote_step(next, &next); if (!dequoted) return -1; if (argv) { ALLOC_GROW(*argv, *nr + 1, *alloc); (*argv)[(*nr)++] = dequoted; } if (array) argv_array_push(array, dequoted); } while (next); return 0; } int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc) { return sq_dequote_to_argv_internal(arg, argv, nr, alloc, NULL); } int sq_dequote_to_argv_array(char *arg, struct argv_array *array) { return sq_dequote_to_argv_internal(arg, NULL, NULL, NULL, array); } /* 1 means: quote as octal * 0 means: quote as octal if (quote_path_fully) * -1 means: never quote * c: quote as "\\c" */ #define X8(x) x, x, x, x, x, x, x, x #define X16(x) X8(x), X8(x) static signed char const sq_lookup[256] = { /* 0 1 2 3 4 5 6 7 */ /* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a', /* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1, /* 0x10 */ X16(1), /* 0x20 */ -1, -1, '"', -1, -1, -1, -1, -1, /* 0x28 */ X16(-1), X16(-1), X16(-1), /* 0x58 */ -1, -1, -1, -1,'\\', -1, -1, -1, /* 0x60 */ X16(-1), X8(-1), /* 0x78 */ -1, -1, -1, -1, -1, -1, -1, 1, /* 0x80 */ /* set to 0 */ }; static inline int sq_must_quote(char c) { return sq_lookup[(unsigned char)c] + quote_path_fully > 0; } /* returns the longest prefix not needing a quote up to maxlen if positive. This stops at the first \0 because it's marked as a character needing an escape */ static size_t next_quote_pos(const char *s, ssize_t maxlen) { size_t len; if (maxlen < 0) { for (len = 0; !sq_must_quote(s[len]); len++); } else { for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++); } return len; } /* * C-style name quoting. * * (1) if sb and fp are both NULL, inspect the input name and counts the * number of bytes that are needed to hold c_style quoted version of name, * counting the double quotes around it but not terminating NUL, and * returns it. * However, if name does not need c_style quoting, it returns 0. * * (2) if sb or fp are not NULL, it emits the c_style quoted version * of name, enclosed with double quotes if asked and needed only. * Return value is the same as in (1). */ static size_t quote_c_style_counted(const char *name, ssize_t maxlen, struct strbuf *sb, FILE *fp, int no_dq) { #undef EMIT #define EMIT(c) \ do { \ if (sb) strbuf_addch(sb, (c)); \ if (fp) fputc((c), fp); \ count++; \ } while (0) #define EMITBUF(s, l) \ do { \ if (sb) strbuf_add(sb, (s), (l)); \ if (fp) fwrite((s), (l), 1, fp); \ count += (l); \ } while (0) size_t len, count = 0; const char *p = name; for (;;) { int ch; len = next_quote_pos(p, maxlen); if (len == maxlen || (maxlen < 0 && !p[len])) break; if (!no_dq && p == name) EMIT('"'); EMITBUF(p, len); EMIT('\\'); p += len; ch = (unsigned char)*p++; if (maxlen >= 0) maxlen -= len + 1; if (sq_lookup[ch] >= ' ') { EMIT(sq_lookup[ch]); } else { EMIT(((ch >> 6) & 03) + '0'); EMIT(((ch >> 3) & 07) + '0'); EMIT(((ch >> 0) & 07) + '0'); } } EMITBUF(p, len); if (p == name) /* no ending quote needed */ return 0; if (!no_dq) EMIT('"'); return count; } size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq) { return quote_c_style_counted(name, -1, sb, fp, nodq); } void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq) { if (quote_c_style(prefix, NULL, NULL, 0) || quote_c_style(path, NULL, NULL, 0)) { if (!nodq) strbuf_addch(sb, '"'); quote_c_style(prefix, sb, NULL, 1); quote_c_style(path, sb, NULL, 1); if (!nodq) strbuf_addch(sb, '"'); } else { strbuf_addstr(sb, prefix); strbuf_addstr(sb, path); } } void write_name_quoted(const char *name, FILE *fp, int terminator) { if (terminator) { quote_c_style(name, NULL, fp, 0); } else { fputs(name, fp); } fputc(terminator, fp); } void write_name_quotedpfx(const char *pfx, size_t pfxlen, const char *name, FILE *fp, int terminator) { int needquote = 0; if (terminator) { needquote = next_quote_pos(pfx, pfxlen) < pfxlen || name[next_quote_pos(name, -1)]; } if (needquote) { fputc('"', fp); quote_c_style_counted(pfx, pfxlen, NULL, fp, 1); quote_c_style(name, NULL, fp, 1); fputc('"', fp); } else { fwrite(pfx, pfxlen, 1, fp); fputs(name, fp); } fputc(terminator, fp); } void write_name_quoted_relative(const char *name, const char *prefix, FILE *fp, int terminator) { struct strbuf sb = STRBUF_INIT; name = relative_path(name, prefix, &sb); write_name_quoted(name, fp, terminator); strbuf_release(&sb); } /* quote path as relative to the given prefix */ char *quote_path_relative(const char *in, const char *prefix, struct strbuf *out) { struct strbuf sb = STRBUF_INIT; const char *rel = relative_path(in, prefix, &sb); strbuf_reset(out); quote_c_style_counted(rel, strlen(rel), out, NULL, 0); strbuf_release(&sb); return out->buf; } /* * C-style name unquoting. * * Quoted should point at the opening double quote. * + Returns 0 if it was able to unquote the string properly, and appends the * result in the strbuf `sb'. * + Returns -1 in case of error, and doesn't touch the strbuf. Though note * that this function will allocate memory in the strbuf, so calling * strbuf_release is mandatory whichever result unquote_c_style returns. * * Updates endp pointer to point at one past the ending double quote if given. */ int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp) { size_t oldlen = sb->len, len; int ch, ac; if (*quoted++ != '"') return -1; for (;;) { len = strcspn(quoted, "\"\\"); strbuf_add(sb, quoted, len); quoted += len; switch (*quoted++) { case '"': if (endp) *endp = quoted; return 0; case '\\': break; default: goto error; } switch ((ch = *quoted++)) { case 'a': ch = '\a'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case 'v': ch = '\v'; break; case '\\': case '"': break; /* verbatim */ /* octal values with first digit over 4 overflow */ case '0': case '1': case '2': case '3': ac = ((ch - '0') << 6); if ((ch = *quoted++) < '0' || '7' < ch) goto error; ac |= ((ch - '0') << 3); if ((ch = *quoted++) < '0' || '7' < ch) goto error; ac |= (ch - '0'); ch = ac; break; default: goto error; } strbuf_addch(sb, ch); } error: strbuf_setlen(sb, oldlen); return -1; } /* quoting as a string literal for other languages */ void perl_quote_buf(struct strbuf *sb, const char *src) { const char sq = '\''; const char bq = '\\'; char c; strbuf_addch(sb, sq); while ((c = *src++)) { 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 = '\''; const char bq = '\\'; const char nl = '\n'; char c; strbuf_addch(sb, sq); while ((c = *src++)) { 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; strbuf_addch(sb, '"'); while ((c = *src++)) { switch (c) { case '[': case ']': case '{': case '}': case '$': case '\\': case '"': strbuf_addch(sb, '\\'); 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, '"'); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
You can’t perform that action at this time.