Sync with 2.31.8
* maint-2.31: (25 commits) Git 2.31.8 tests: avoid using `test_i18ncmp` Git 2.30.9 gettext: avoid using gettext if the locale dir is not present apply --reject: overwrite existing `.rej` symlink if it exists http.c: clear the 'finished' member once we are done with it clone.c: avoid "exceeds maximum object size" error with GCC v12.x range-diff: use ssize_t for parsed "len" in read_patches() range-diff: handle unterminated lines in read_patches() range-diff: drop useless "offset" variable from read_patches() t5604: GETTEXT_POISON fix, conclusion t5604: GETTEXT_POISON fix, part 1 t5619: GETTEXT_POISON fix t0003: GETTEXT_POISON fix, conclusion t0003: GETTEXT_POISON fix, part 1 t0033: GETTEXT_POISON fix http: support CURLOPT_PROTOCOLS_STR http: prefer CURLOPT_SEEKFUNCTION to CURLOPT_IOCTLFUNCTION http-push: prefer CURLOPT_UPLOAD to CURLOPT_PUT ci: install python on ubuntu ci: use the same version of p4 on both Linux and macOS ...
This commit is contained in:
commit
31f7fe5e34
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@ -287,7 +287,7 @@ jobs:
|
|||||||
pool: ubuntu-latest
|
pool: ubuntu-latest
|
||||||
- jobname: linux-gcc
|
- jobname: linux-gcc
|
||||||
cc: gcc
|
cc: gcc
|
||||||
pool: ubuntu-latest
|
pool: ubuntu-20.04
|
||||||
- jobname: osx-clang
|
- jobname: osx-clang
|
||||||
cc: clang
|
cc: clang
|
||||||
pool: macos-latest
|
pool: macos-latest
|
||||||
@ -345,7 +345,7 @@ jobs:
|
|||||||
if: needs.ci-config.outputs.enabled == 'yes'
|
if: needs.ci-config.outputs.enabled == 'yes'
|
||||||
env:
|
env:
|
||||||
jobname: StaticAnalysis
|
jobname: StaticAnalysis
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- run: ci/install-dependencies.sh
|
- run: ci/install-dependencies.sh
|
||||||
|
43
Documentation/RelNotes/2.30.9.txt
Normal file
43
Documentation/RelNotes/2.30.9.txt
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
Git v2.30.9 Release Notes
|
||||||
|
=========================
|
||||||
|
|
||||||
|
This release addresses the security issues CVE-2023-25652,
|
||||||
|
CVE-2023-25815, and CVE-2023-29007.
|
||||||
|
|
||||||
|
|
||||||
|
Fixes since v2.30.8
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* CVE-2023-25652:
|
||||||
|
|
||||||
|
By feeding specially crafted input to `git apply --reject`, a
|
||||||
|
path outside the working tree can be overwritten with partially
|
||||||
|
controlled contents (corresponding to the rejected hunk(s) from
|
||||||
|
the given patch).
|
||||||
|
|
||||||
|
* CVE-2023-25815:
|
||||||
|
|
||||||
|
When Git is compiled with runtime prefix support and runs without
|
||||||
|
translated messages, it still used the gettext machinery to
|
||||||
|
display messages, which subsequently potentially looked for
|
||||||
|
translated messages in unexpected places. This allowed for
|
||||||
|
malicious placement of crafted messages.
|
||||||
|
|
||||||
|
* CVE-2023-29007:
|
||||||
|
|
||||||
|
When renaming or deleting a section from a configuration file,
|
||||||
|
certain malicious configuration values may be misinterpreted as
|
||||||
|
the beginning of a new configuration section, leading to arbitrary
|
||||||
|
configuration injection.
|
||||||
|
|
||||||
|
Credit for finding CVE-2023-25652 goes to Ry0taK, and the fix was
|
||||||
|
developed by Taylor Blau, Junio C Hamano and Johannes Schindelin,
|
||||||
|
with the help of Linus Torvalds.
|
||||||
|
|
||||||
|
Credit for finding CVE-2023-25815 goes to Maxime Escourbiac and
|
||||||
|
Yassine BENGANA of Michelin, and the fix was developed by Johannes
|
||||||
|
Schindelin.
|
||||||
|
|
||||||
|
Credit for finding CVE-2023-29007 goes to André Baptista and Vítor Pinho
|
||||||
|
of Ethiack, and the fix was developed by Taylor Blau, and Johannes
|
||||||
|
Schindelin, with help from Jeff King, and Patrick Steinhardt.
|
6
Documentation/RelNotes/2.31.8.txt
Normal file
6
Documentation/RelNotes/2.31.8.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Git v2.31.8 Release Notes
|
||||||
|
=========================
|
||||||
|
|
||||||
|
This release merges the fixes that appear in v2.30.9 to address the
|
||||||
|
security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007;
|
||||||
|
see the release notes for that version for details.
|
4
INSTALL
4
INSTALL
@ -145,6 +145,10 @@ Issues of note:
|
|||||||
patches into an IMAP mailbox, you do not have to have them
|
patches into an IMAP mailbox, you do not have to have them
|
||||||
(use NO_CURL).
|
(use NO_CURL).
|
||||||
|
|
||||||
|
Git requires version "7.19.5" or later of "libcurl" to build
|
||||||
|
without NO_CURL. This version requirement may be bumped in
|
||||||
|
the future.
|
||||||
|
|
||||||
- "expat" library; git-http-push uses it for remote lock
|
- "expat" library; git-http-push uses it for remote lock
|
||||||
management over DAV. Similar to "curl" above, this is optional
|
management over DAV. Similar to "curl" above, this is optional
|
||||||
(with NO_EXPAT).
|
(with NO_EXPAT).
|
||||||
|
14
apply.c
14
apply.c
@ -4560,7 +4560,7 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
|
|||||||
FILE *rej;
|
FILE *rej;
|
||||||
char namebuf[PATH_MAX];
|
char namebuf[PATH_MAX];
|
||||||
struct fragment *frag;
|
struct fragment *frag;
|
||||||
int cnt = 0;
|
int fd, cnt = 0;
|
||||||
struct strbuf sb = STRBUF_INIT;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
|
|
||||||
for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) {
|
for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) {
|
||||||
@ -4600,7 +4600,17 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
|
|||||||
memcpy(namebuf, patch->new_name, cnt);
|
memcpy(namebuf, patch->new_name, cnt);
|
||||||
memcpy(namebuf + cnt, ".rej", 5);
|
memcpy(namebuf + cnt, ".rej", 5);
|
||||||
|
|
||||||
rej = fopen(namebuf, "w");
|
fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
if (errno != EEXIST)
|
||||||
|
return error_errno(_("cannot open %s"), namebuf);
|
||||||
|
if (unlink(namebuf))
|
||||||
|
return error_errno(_("cannot unlink '%s'"), namebuf);
|
||||||
|
fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
|
||||||
|
if (fd < 0)
|
||||||
|
return error_errno(_("cannot open %s"), namebuf);
|
||||||
|
}
|
||||||
|
rej = fdopen(fd, "w");
|
||||||
if (!rej)
|
if (!rej)
|
||||||
return error_errno(_("cannot open %s"), namebuf);
|
return error_errno(_("cannot open %s"), namebuf);
|
||||||
|
|
||||||
|
@ -254,6 +254,15 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
|
|||||||
end--;
|
end--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It should not be possible to overflow `ptrdiff_t` by passing in an
|
||||||
|
* insanely long URL, but GCC does not know that and will complain
|
||||||
|
* without this check.
|
||||||
|
*/
|
||||||
|
if (end - start < 0)
|
||||||
|
die(_("No directory name could be guessed.\n"
|
||||||
|
"Please specify a directory on the command line"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Strip trailing port number if we've got only a
|
* Strip trailing port number if we've got only a
|
||||||
* hostname (that is, there is no dir separator but a
|
* hostname (that is, there is no dir separator but a
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
. ${0%/*}/lib.sh
|
. ${0%/*}/lib.sh
|
||||||
|
|
||||||
P4WHENCE=http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION
|
P4WHENCE=https://cdist2.perforce.com/perforce/r21.2
|
||||||
LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION
|
LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION
|
||||||
UBUNTU_COMMON_PKGS="make libssl-dev libcurl4-openssl-dev libexpat-dev
|
UBUNTU_COMMON_PKGS="make libssl-dev libcurl4-openssl-dev libexpat-dev
|
||||||
tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl
|
tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl
|
||||||
@ -16,7 +16,7 @@ linux-clang|linux-gcc)
|
|||||||
sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
|
sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
|
||||||
sudo apt-get -q update
|
sudo apt-get -q update
|
||||||
sudo apt-get -q -y install language-pack-is libsvn-perl apache2 \
|
sudo apt-get -q -y install language-pack-is libsvn-perl apache2 \
|
||||||
$UBUNTU_COMMON_PKGS
|
$UBUNTU_COMMON_PKGS $PYTHON_PACKAGE
|
||||||
case "$jobname" in
|
case "$jobname" in
|
||||||
linux-gcc)
|
linux-gcc)
|
||||||
sudo apt-get -q -y install gcc-8
|
sudo apt-get -q -y install gcc-8
|
||||||
@ -44,13 +44,15 @@ osx-clang|osx-gcc)
|
|||||||
test -z "$BREW_INSTALL_PACKAGES" ||
|
test -z "$BREW_INSTALL_PACKAGES" ||
|
||||||
brew install $BREW_INSTALL_PACKAGES
|
brew install $BREW_INSTALL_PACKAGES
|
||||||
brew link --force gettext
|
brew link --force gettext
|
||||||
brew install --cask --no-quarantine perforce || {
|
mkdir -p $HOME/bin
|
||||||
# Update the definitions and try again
|
(
|
||||||
cask_repo="$(brew --repository)"/Library/Taps/homebrew/homebrew-cask &&
|
cd $HOME/bin
|
||||||
git -C "$cask_repo" pull --no-stat --ff-only &&
|
wget -q "$P4WHENCE/bin.macosx1015x86_64/helix-core-server.tgz" &&
|
||||||
brew install --cask --no-quarantine perforce
|
tar -xf helix-core-server.tgz &&
|
||||||
} ||
|
sudo xattr -d com.apple.quarantine p4 p4d 2>/dev/null || true
|
||||||
brew install homebrew/cask/perforce
|
)
|
||||||
|
PATH="$PATH:${HOME}/bin"
|
||||||
|
export PATH
|
||||||
case "$jobname" in
|
case "$jobname" in
|
||||||
osx-gcc)
|
osx-gcc)
|
||||||
brew install gcc@9
|
brew install gcc@9
|
||||||
@ -81,9 +83,9 @@ esac
|
|||||||
if type p4d >/dev/null && type p4 >/dev/null
|
if type p4d >/dev/null && type p4 >/dev/null
|
||||||
then
|
then
|
||||||
echo "$(tput setaf 6)Perforce Server Version$(tput sgr0)"
|
echo "$(tput setaf 6)Perforce Server Version$(tput sgr0)"
|
||||||
p4d -V | grep Rev.
|
p4d -V
|
||||||
echo "$(tput setaf 6)Perforce Client Version$(tput sgr0)"
|
echo "$(tput setaf 6)Perforce Client Version$(tput sgr0)"
|
||||||
p4 -V | grep Rev.
|
p4 -V
|
||||||
fi
|
fi
|
||||||
if type git-lfs >/dev/null
|
if type git-lfs >/dev/null
|
||||||
then
|
then
|
||||||
|
@ -184,13 +184,13 @@ export SKIP_DASHED_BUILT_INS=YesPlease
|
|||||||
|
|
||||||
case "$jobname" in
|
case "$jobname" in
|
||||||
linux-clang|linux-gcc)
|
linux-clang|linux-gcc)
|
||||||
|
PYTHON_PACKAGE=python2
|
||||||
if [ "$jobname" = linux-gcc ]
|
if [ "$jobname" = linux-gcc ]
|
||||||
then
|
then
|
||||||
export CC=gcc-8
|
export CC=gcc-8
|
||||||
MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python3"
|
PYTHON_PACKAGE=python3
|
||||||
else
|
|
||||||
MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python2"
|
|
||||||
fi
|
fi
|
||||||
|
MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/$PYTHON_PACKAGE"
|
||||||
|
|
||||||
export GIT_TEST_HTTPD=true
|
export GIT_TEST_HTTPD=true
|
||||||
|
|
||||||
@ -199,7 +199,6 @@ linux-clang|linux-gcc)
|
|||||||
# were recorded in the Homebrew database upon creating the OS X
|
# were recorded in the Homebrew database upon creating the OS X
|
||||||
# image.
|
# image.
|
||||||
# Keep that in mind when you encounter a broken OS X build!
|
# Keep that in mind when you encounter a broken OS X build!
|
||||||
export LINUX_P4_VERSION="16.2"
|
|
||||||
export LINUX_GIT_LFS_VERSION="1.5.2"
|
export LINUX_GIT_LFS_VERSION="1.5.2"
|
||||||
|
|
||||||
P4_PATH="$HOME/custom/p4"
|
P4_PATH="$HOME/custom/p4"
|
||||||
|
@ -323,7 +323,6 @@ static NOINLINE void RemoveCacheEntries(nedpool *p, threadcache *tc, unsigned in
|
|||||||
}
|
}
|
||||||
static void DestroyCaches(nedpool *p) THROWSPEC
|
static void DestroyCaches(nedpool *p) THROWSPEC
|
||||||
{
|
{
|
||||||
if(p->caches)
|
|
||||||
{
|
{
|
||||||
threadcache *tc;
|
threadcache *tc;
|
||||||
int n;
|
int n;
|
||||||
|
@ -43,6 +43,7 @@ void syslog(int priority, const char *fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
while ((pos = strstr(str, "%1")) != NULL) {
|
while ((pos = strstr(str, "%1")) != NULL) {
|
||||||
|
size_t offset = pos - str;
|
||||||
char *oldstr = str;
|
char *oldstr = str;
|
||||||
str = realloc(str, st_add(++str_len, 1));
|
str = realloc(str, st_add(++str_len, 1));
|
||||||
if (!str) {
|
if (!str) {
|
||||||
@ -50,6 +51,7 @@ void syslog(int priority, const char *fmt, ...)
|
|||||||
warning_errno("realloc failed");
|
warning_errno("realloc failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
pos = str + offset;
|
||||||
memmove(pos + 2, pos + 1, strlen(pos));
|
memmove(pos + 2, pos + 1, strlen(pos));
|
||||||
pos[1] = ' ';
|
pos[1] = ' ';
|
||||||
}
|
}
|
||||||
|
36
config.c
36
config.c
@ -3198,9 +3198,10 @@ void git_config_set_multivar(const char *key, const char *value,
|
|||||||
flags);
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int section_name_match (const char *buf, const char *name)
|
static size_t section_name_match (const char *buf, const char *name)
|
||||||
{
|
{
|
||||||
int i = 0, j = 0, dot = 0;
|
size_t i = 0, j = 0;
|
||||||
|
int dot = 0;
|
||||||
if (buf[i] != '[')
|
if (buf[i] != '[')
|
||||||
return 0;
|
return 0;
|
||||||
for (i = 1; buf[i] && buf[i] != ']'; i++) {
|
for (i = 1; buf[i] && buf[i] != ']'; i++) {
|
||||||
@ -3253,6 +3254,8 @@ static int section_name_is_ok(const char *name)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GIT_CONFIG_MAX_LINE_LEN (512 * 1024)
|
||||||
|
|
||||||
/* if new_name == NULL, the section is removed instead */
|
/* if new_name == NULL, the section is removed instead */
|
||||||
static int git_config_copy_or_rename_section_in_file(const char *config_filename,
|
static int git_config_copy_or_rename_section_in_file(const char *config_filename,
|
||||||
const char *old_name,
|
const char *old_name,
|
||||||
@ -3262,11 +3265,12 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
|
|||||||
char *filename_buf = NULL;
|
char *filename_buf = NULL;
|
||||||
struct lock_file lock = LOCK_INIT;
|
struct lock_file lock = LOCK_INIT;
|
||||||
int out_fd;
|
int out_fd;
|
||||||
char buf[1024];
|
struct strbuf buf = STRBUF_INIT;
|
||||||
FILE *config_file = NULL;
|
FILE *config_file = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct strbuf copystr = STRBUF_INIT;
|
struct strbuf copystr = STRBUF_INIT;
|
||||||
struct config_store_data store;
|
struct config_store_data store;
|
||||||
|
uint32_t line_nr = 0;
|
||||||
|
|
||||||
memset(&store, 0, sizeof(store));
|
memset(&store, 0, sizeof(store));
|
||||||
|
|
||||||
@ -3303,16 +3307,25 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (fgets(buf, sizeof(buf), config_file)) {
|
while (!strbuf_getwholeline(&buf, config_file, '\n')) {
|
||||||
unsigned i;
|
size_t i, length;
|
||||||
int length;
|
|
||||||
int is_section = 0;
|
int is_section = 0;
|
||||||
char *output = buf;
|
char *output = buf.buf;
|
||||||
for (i = 0; buf[i] && isspace(buf[i]); i++)
|
|
||||||
|
line_nr++;
|
||||||
|
|
||||||
|
if (buf.len >= GIT_CONFIG_MAX_LINE_LEN) {
|
||||||
|
ret = error(_("refusing to work with overly long line "
|
||||||
|
"in '%s' on line %"PRIuMAX),
|
||||||
|
config_filename, (uintmax_t)line_nr);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; buf.buf[i] && isspace(buf.buf[i]); i++)
|
||||||
; /* do nothing */
|
; /* do nothing */
|
||||||
if (buf[i] == '[') {
|
if (buf.buf[i] == '[') {
|
||||||
/* it's a section */
|
/* it's a section */
|
||||||
int offset;
|
size_t offset;
|
||||||
is_section = 1;
|
is_section = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3329,7 +3342,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
|
|||||||
strbuf_reset(©str);
|
strbuf_reset(©str);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = section_name_match(&buf[i], old_name);
|
offset = section_name_match(&buf.buf[i], old_name);
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
ret++;
|
ret++;
|
||||||
if (new_name == NULL) {
|
if (new_name == NULL) {
|
||||||
@ -3404,6 +3417,7 @@ out:
|
|||||||
out_no_rollback:
|
out_no_rollback:
|
||||||
free(filename_buf);
|
free(filename_buf);
|
||||||
config_store_data_clear(&store);
|
config_store_data_clear(&store);
|
||||||
|
strbuf_release(&buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +101,8 @@ static void init_gettext_charset(const char *domain)
|
|||||||
setlocale(LC_CTYPE, "C");
|
setlocale(LC_CTYPE, "C");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_gettext_enabled = 0;
|
||||||
|
|
||||||
void git_setup_gettext(void)
|
void git_setup_gettext(void)
|
||||||
{
|
{
|
||||||
const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);
|
const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);
|
||||||
@ -120,6 +122,8 @@ void git_setup_gettext(void)
|
|||||||
init_gettext_charset("git");
|
init_gettext_charset("git");
|
||||||
textdomain("git");
|
textdomain("git");
|
||||||
|
|
||||||
|
git_gettext_enabled = 1;
|
||||||
|
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,9 +29,11 @@
|
|||||||
#define FORMAT_PRESERVING(n) __attribute__((format_arg(n)))
|
#define FORMAT_PRESERVING(n) __attribute__((format_arg(n)))
|
||||||
|
|
||||||
#ifndef NO_GETTEXT
|
#ifndef NO_GETTEXT
|
||||||
|
extern int git_gettext_enabled;
|
||||||
void git_setup_gettext(void);
|
void git_setup_gettext(void);
|
||||||
int gettext_width(const char *s);
|
int gettext_width(const char *s);
|
||||||
#else
|
#else
|
||||||
|
#define git_gettext_enabled (0)
|
||||||
static inline void git_setup_gettext(void)
|
static inline void git_setup_gettext(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -45,12 +47,16 @@ static inline FORMAT_PRESERVING(1) const char *_(const char *msgid)
|
|||||||
{
|
{
|
||||||
if (!*msgid)
|
if (!*msgid)
|
||||||
return "";
|
return "";
|
||||||
|
if (!git_gettext_enabled)
|
||||||
|
return msgid;
|
||||||
return gettext(msgid);
|
return gettext(msgid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2)
|
static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2)
|
||||||
const char *Q_(const char *msgid, const char *plu, unsigned long n)
|
const char *Q_(const char *msgid, const char *plu, unsigned long n)
|
||||||
{
|
{
|
||||||
|
if (!git_gettext_enabled)
|
||||||
|
return n == 1 ? msgid : plu;
|
||||||
return ngettext(msgid, plu, n);
|
return ngettext(msgid, plu, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,14 +198,14 @@ static void curl_setup_http(CURL *curl, const char *url,
|
|||||||
const char *custom_req, struct buffer *buffer,
|
const char *custom_req, struct buffer *buffer,
|
||||||
curl_write_callback write_fn)
|
curl_write_callback write_fn)
|
||||||
{
|
{
|
||||||
curl_easy_setopt(curl, CURLOPT_PUT, 1);
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
curl_easy_setopt(curl, CURLOPT_INFILE, buffer);
|
curl_easy_setopt(curl, CURLOPT_INFILE, buffer);
|
||||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len);
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len);
|
||||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
|
curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_buffer);
|
||||||
curl_easy_setopt(curl, CURLOPT_IOCTLDATA, buffer);
|
curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer);
|
||||||
#endif
|
#endif
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn);
|
||||||
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
|
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
|
||||||
|
105
http.c
105
http.c
@ -186,22 +186,20 @@ size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
|
|||||||
return size / eltsize;
|
return size / eltsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
|
int seek_buffer(void *clientp, curl_off_t offset, int origin)
|
||||||
{
|
{
|
||||||
struct buffer *buffer = clientp;
|
struct buffer *buffer = clientp;
|
||||||
|
|
||||||
switch (cmd) {
|
if (origin != SEEK_SET)
|
||||||
case CURLIOCMD_NOP:
|
BUG("seek_buffer only handles SEEK_SET");
|
||||||
return CURLIOE_OK;
|
if (offset < 0 || offset >= buffer->buf.len) {
|
||||||
|
error("curl seek would be outside of buffer");
|
||||||
case CURLIOCMD_RESTARTREAD:
|
return CURL_SEEKFUNC_FAIL;
|
||||||
buffer->posn = 0;
|
|
||||||
return CURLIOE_OK;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return CURLIOE_UNKNOWNCMD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer->posn = offset;
|
||||||
|
return CURL_SEEKFUNC_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -810,20 +808,37 @@ void setup_curl_trace(CURL *handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CURLPROTO_HTTP
|
#ifdef CURLPROTO_HTTP
|
||||||
static long get_curl_allowed_protocols(int from_user)
|
static void proto_list_append(struct strbuf *list, const char *proto)
|
||||||
{
|
{
|
||||||
long allowed_protocols = 0;
|
if (!list)
|
||||||
|
return;
|
||||||
|
if (list->len)
|
||||||
|
strbuf_addch(list, ',');
|
||||||
|
strbuf_addstr(list, proto);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_transport_allowed("http", from_user))
|
static long get_curl_allowed_protocols(int from_user, struct strbuf *list)
|
||||||
allowed_protocols |= CURLPROTO_HTTP;
|
{
|
||||||
if (is_transport_allowed("https", from_user))
|
long bits = 0;
|
||||||
allowed_protocols |= CURLPROTO_HTTPS;
|
|
||||||
if (is_transport_allowed("ftp", from_user))
|
|
||||||
allowed_protocols |= CURLPROTO_FTP;
|
|
||||||
if (is_transport_allowed("ftps", from_user))
|
|
||||||
allowed_protocols |= CURLPROTO_FTPS;
|
|
||||||
|
|
||||||
return allowed_protocols;
|
if (is_transport_allowed("http", from_user)) {
|
||||||
|
bits |= CURLPROTO_HTTP;
|
||||||
|
proto_list_append(list, "http");
|
||||||
|
}
|
||||||
|
if (is_transport_allowed("https", from_user)) {
|
||||||
|
bits |= CURLPROTO_HTTPS;
|
||||||
|
proto_list_append(list, "https");
|
||||||
|
}
|
||||||
|
if (is_transport_allowed("ftp", from_user)) {
|
||||||
|
bits |= CURLPROTO_FTP;
|
||||||
|
proto_list_append(list, "ftp");
|
||||||
|
}
|
||||||
|
if (is_transport_allowed("ftps", from_user)) {
|
||||||
|
bits |= CURLPROTO_FTPS;
|
||||||
|
proto_list_append(list, "ftps");
|
||||||
|
}
|
||||||
|
|
||||||
|
return bits;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -981,10 +996,24 @@ static CURL *get_curl_handle(void)
|
|||||||
curl_easy_setopt(result, CURLOPT_POST301, 1);
|
curl_easy_setopt(result, CURLOPT_POST301, 1);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CURLPROTO_HTTP
|
#ifdef CURLPROTO_HTTP
|
||||||
|
#if LIBCURL_VERSION_NUM >= 0x075500
|
||||||
|
{
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
|
get_curl_allowed_protocols(0, &buf);
|
||||||
|
curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS_STR, buf.buf);
|
||||||
|
strbuf_reset(&buf);
|
||||||
|
|
||||||
|
get_curl_allowed_protocols(-1, &buf);
|
||||||
|
curl_easy_setopt(result, CURLOPT_PROTOCOLS_STR, buf.buf);
|
||||||
|
strbuf_release(&buf);
|
||||||
|
}
|
||||||
|
#else
|
||||||
curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS,
|
curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS,
|
||||||
get_curl_allowed_protocols(0));
|
get_curl_allowed_protocols(0, NULL));
|
||||||
curl_easy_setopt(result, CURLOPT_PROTOCOLS,
|
curl_easy_setopt(result, CURLOPT_PROTOCOLS,
|
||||||
get_curl_allowed_protocols(-1));
|
get_curl_allowed_protocols(-1, NULL));
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
warning(_("Protocol restrictions not supported with cURL < 7.19.4"));
|
warning(_("Protocol restrictions not supported with cURL < 7.19.4"));
|
||||||
#endif
|
#endif
|
||||||
@ -1523,6 +1552,32 @@ void run_active_slot(struct active_request_slot *slot)
|
|||||||
finish_active_slot(slot);
|
finish_active_slot(slot);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The value of slot->finished we set before the loop was used
|
||||||
|
* to set our "finished" variable when our request completed.
|
||||||
|
*
|
||||||
|
* 1. The slot may not have been reused for another requst
|
||||||
|
* yet, in which case it still has &finished.
|
||||||
|
*
|
||||||
|
* 2. The slot may already be in-use to serve another request,
|
||||||
|
* which can further be divided into two cases:
|
||||||
|
*
|
||||||
|
* (a) If call run_active_slot() hasn't been called for that
|
||||||
|
* other request, slot->finished would have been cleared
|
||||||
|
* by get_active_slot() and has NULL.
|
||||||
|
*
|
||||||
|
* (b) If the request did call run_active_slot(), then the
|
||||||
|
* call would have updated slot->finished at the beginning
|
||||||
|
* of this function, and with the clearing of the member
|
||||||
|
* below, we would find that slot->finished is now NULL.
|
||||||
|
*
|
||||||
|
* In all cases, slot->finished has no useful information to
|
||||||
|
* anybody at this point. Some compilers warn us for
|
||||||
|
* attempting to smuggle a pointer that is about to become
|
||||||
|
* invalid, i.e. &finished. We clear it here to assure them.
|
||||||
|
*/
|
||||||
|
slot->finished = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_active_slot(struct active_request_slot *slot)
|
static void release_active_slot(struct active_request_slot *slot)
|
||||||
|
8
http.h
8
http.h
@ -41,8 +41,8 @@
|
|||||||
#define CURLE_HTTP_RETURNED_ERROR CURLE_HTTP_NOT_FOUND
|
#define CURLE_HTTP_RETURNED_ERROR CURLE_HTTP_NOT_FOUND
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LIBCURL_VERSION_NUM < 0x070c03
|
#if LIBCURL_VERSION_NUM < 0x071200
|
||||||
#define NO_CURL_IOCTL
|
#define NO_CURL_SEEK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -82,8 +82,8 @@ struct buffer {
|
|||||||
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
||||||
size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
||||||
size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
|
int seek_buffer(void *clientp, curl_off_t offset, int origin);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Slot lifecycle functions */
|
/* Slot lifecycle functions */
|
||||||
|
29
range-diff.c
29
range-diff.c
@ -26,17 +26,6 @@ struct patch_util {
|
|||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static size_t find_end_of_line(char *buffer, unsigned long size)
|
|
||||||
{
|
|
||||||
char *eol = memchr(buffer, '\n', size);
|
|
||||||
|
|
||||||
if (!eol)
|
|
||||||
return size;
|
|
||||||
|
|
||||||
*eol = '\0';
|
|
||||||
return eol + 1 - buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads the patches into a string list, with the `util` field being populated
|
* Reads the patches into a string list, with the `util` field being populated
|
||||||
* as struct object_id (will need to be free()d).
|
* as struct object_id (will need to be free()d).
|
||||||
@ -49,7 +38,7 @@ static int read_patches(const char *range, struct string_list *list,
|
|||||||
struct patch_util *util = NULL;
|
struct patch_util *util = NULL;
|
||||||
int in_header = 1;
|
int in_header = 1;
|
||||||
char *line, *current_filename = NULL;
|
char *line, *current_filename = NULL;
|
||||||
int offset, len;
|
ssize_t len;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
strvec_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
|
strvec_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
|
||||||
@ -86,11 +75,18 @@ static int read_patches(const char *range, struct string_list *list,
|
|||||||
|
|
||||||
line = contents.buf;
|
line = contents.buf;
|
||||||
size = contents.len;
|
size = contents.len;
|
||||||
for (offset = 0; size > 0; offset += len, size -= len, line += len) {
|
for (; size > 0; size -= len, line += len) {
|
||||||
const char *p;
|
const char *p;
|
||||||
|
char *eol;
|
||||||
|
|
||||||
|
eol = memchr(line, '\n', size);
|
||||||
|
if (eol) {
|
||||||
|
*eol = '\0';
|
||||||
|
len = eol + 1 - line;
|
||||||
|
} else {
|
||||||
|
len = size;
|
||||||
|
}
|
||||||
|
|
||||||
len = find_end_of_line(line, size);
|
|
||||||
line[len - 1] = '\0';
|
|
||||||
if (skip_prefix(line, "commit ", &p)) {
|
if (skip_prefix(line, "commit ", &p)) {
|
||||||
if (util) {
|
if (util) {
|
||||||
string_list_append(list, buf.buf)->util = util;
|
string_list_append(list, buf.buf)->util = util;
|
||||||
@ -132,7 +128,8 @@ static int read_patches(const char *range, struct string_list *list,
|
|||||||
strbuf_addch(&buf, '\n');
|
strbuf_addch(&buf, '\n');
|
||||||
if (!util->diff_offset)
|
if (!util->diff_offset)
|
||||||
util->diff_offset = buf.len;
|
util->diff_offset = buf.len;
|
||||||
line[len - 1] = '\n';
|
if (eol)
|
||||||
|
*eol = '\n';
|
||||||
orig_len = len;
|
orig_len = len;
|
||||||
len = parse_git_diff_header(&root, &linenr, 0, line,
|
len = parse_git_diff_header(&root, &linenr, 0, line,
|
||||||
len, size, &patch);
|
len, size, &patch);
|
||||||
|
@ -709,26 +709,24 @@ static size_t rpc_out(void *ptr, size_t eltsize,
|
|||||||
return avail;
|
return avail;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
|
static int rpc_seek(void *clientp, curl_off_t offset, int origin)
|
||||||
{
|
{
|
||||||
struct rpc_state *rpc = clientp;
|
struct rpc_state *rpc = clientp;
|
||||||
|
|
||||||
switch (cmd) {
|
if (origin != SEEK_SET)
|
||||||
case CURLIOCMD_NOP:
|
BUG("rpc_seek only handles SEEK_SET, not %d", origin);
|
||||||
return CURLIOE_OK;
|
|
||||||
|
|
||||||
case CURLIOCMD_RESTARTREAD:
|
if (rpc->initial_buffer) {
|
||||||
if (rpc->initial_buffer) {
|
if (offset < 0 || offset > rpc->len) {
|
||||||
rpc->pos = 0;
|
error("curl seek would be outside of rpc buffer");
|
||||||
return CURLIOE_OK;
|
return CURL_SEEKFUNC_FAIL;
|
||||||
}
|
}
|
||||||
error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
|
rpc->pos = offset;
|
||||||
return CURLIOE_FAILRESTART;
|
return CURL_SEEKFUNC_OK;
|
||||||
|
|
||||||
default:
|
|
||||||
return CURLIOE_UNKNOWNCMD;
|
|
||||||
}
|
}
|
||||||
|
error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
|
||||||
|
return CURL_SEEKFUNC_FAIL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -949,9 +947,9 @@ retry:
|
|||||||
rpc->initial_buffer = 1;
|
rpc->initial_buffer = 1;
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out);
|
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out);
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc);
|
curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc);
|
||||||
#ifndef NO_CURL_IOCTL
|
#ifndef NO_CURL_SEEK
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, rpc_ioctl);
|
curl_easy_setopt(slot->curl, CURLOPT_SEEKFUNCTION, rpc_seek);
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, rpc);
|
curl_easy_setopt(slot->curl, CURLOPT_SEEKDATA, rpc);
|
||||||
#endif
|
#endif
|
||||||
if (options.verbosity > 1) {
|
if (options.verbosity > 1) {
|
||||||
fprintf(stderr, "POST %s (chunked)\n", rpc->service_name);
|
fprintf(stderr, "POST %s (chunked)\n", rpc->service_name);
|
||||||
|
@ -9,7 +9,7 @@ export GIT_TEST_ASSUME_DIFFERENT_OWNER
|
|||||||
|
|
||||||
expect_rejected_dir () {
|
expect_rejected_dir () {
|
||||||
test_must_fail git status 2>err &&
|
test_must_fail git status 2>err &&
|
||||||
grep "safe.directory" err
|
grep "dubious ownership" err
|
||||||
}
|
}
|
||||||
|
|
||||||
test_expect_success 'safe.directory is not set' '
|
test_expect_success 'safe.directory is not set' '
|
||||||
|
@ -616,6 +616,36 @@ test_expect_success 'renaming to bogus section is rejected' '
|
|||||||
test_must_fail git config --rename-section branch.zwei "bogus name"
|
test_must_fail git config --rename-section branch.zwei "bogus name"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'renaming a section with a long line' '
|
||||||
|
{
|
||||||
|
printf "[b]\\n" &&
|
||||||
|
printf " c = d %1024s [a] e = f\\n" " " &&
|
||||||
|
printf "[a] g = h\\n"
|
||||||
|
} >y &&
|
||||||
|
git config -f y --rename-section a xyz &&
|
||||||
|
test_must_fail git config -f y b.e
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'renaming an embedded section with a long line' '
|
||||||
|
{
|
||||||
|
printf "[b]\\n" &&
|
||||||
|
printf " c = d %1024s [a] [foo] e = f\\n" " " &&
|
||||||
|
printf "[a] g = h\\n"
|
||||||
|
} >y &&
|
||||||
|
git config -f y --rename-section a xyz &&
|
||||||
|
test_must_fail git config -f y foo.e
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'renaming a section with an overly-long line' '
|
||||||
|
{
|
||||||
|
printf "[b]\\n" &&
|
||||||
|
printf " c = d %525000s e" " " &&
|
||||||
|
printf "[a] g = h\\n"
|
||||||
|
} >y &&
|
||||||
|
test_must_fail git config -f y --rename-section a xyz 2>err &&
|
||||||
|
grep "refusing to work with overly long line in .y. on line 2" err
|
||||||
|
'
|
||||||
|
|
||||||
cat >> .git/config << EOF
|
cat >> .git/config << EOF
|
||||||
[branch "zwei"] a = 1 [branch "vier"]
|
[branch "zwei"] a = 1 [branch "vier"]
|
||||||
EOF
|
EOF
|
||||||
|
@ -125,4 +125,19 @@ test_expect_success SYMLINKS 'symlink escape when deleting file' '
|
|||||||
test_path_is_file .git/delete-me
|
test_path_is_file .git/delete-me
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success SYMLINKS '--reject removes .rej symlink if it exists' '
|
||||||
|
test_when_finished "git reset --hard && git clean -dfx" &&
|
||||||
|
|
||||||
|
test_commit file &&
|
||||||
|
echo modified >file.t &&
|
||||||
|
git diff -- file.t >patch &&
|
||||||
|
echo modified-again >file.t &&
|
||||||
|
|
||||||
|
ln -s foo file.t.rej &&
|
||||||
|
test_must_fail git apply patch --reject 2>err &&
|
||||||
|
test_i18ngrep "Rejected hunk" err &&
|
||||||
|
test_path_is_missing foo &&
|
||||||
|
test_path_is_file file.t.rej
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user