Skip to content

Commit 676cdde

Browse files
committed
Sync with 2.40.4
* maint-2.40: Git 2.40.4 credential: disallow Carriage Returns in the protocol by default credential: sanitize the user prompt credential_format(): also encode <host>[:<port>] t7300: work around platform-specific behaviour with long paths on MinGW compat/regex: fix argument order to calloc(3) mingw: drop bogus (and unneeded) declaration of `_pgmptr` ci: remove 'Upload failed tests' directories' step from linux32 jobs
2 parents 0dc9cad + 54a3711 commit 676cdde

File tree

16 files changed

+131
-53
lines changed

16 files changed

+131
-53
lines changed

.github/workflows/main.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,12 +334,6 @@ jobs:
334334
with:
335335
name: failed-tests-${{matrix.vector.jobname}}
336336
path: ${{env.FAILED_TEST_ARTIFACTS}}
337-
- name: Upload failed tests' directories
338-
if: failure() && env.FAILED_TEST_ARTIFACTS != '' && matrix.vector.jobname == 'linux32'
339-
uses: actions/upload-artifact@v1 # cannot be upgraded because Node.js Actions aren't supported in this container
340-
with:
341-
name: failed-tests-${{matrix.vector.jobname}}
342-
path: ${{env.FAILED_TEST_ARTIFACTS}}
343337
static-analysis:
344338
needs: ci-config
345339
if: needs.ci-config.outputs.enabled == 'yes'

Documentation/RelNotes/2.40.4.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.40.4 Release Notes
2+
=========================
3+
4+
This release lets Git refuse to accept URLs that contain control
5+
sequences. This addresses CVE-2024-50349 and CVE-2024-52006.

Documentation/config/credential.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ credential.useHttpPath::
1414
or https URL to be important. Defaults to false. See
1515
linkgit:gitcredentials[7] for more information.
1616

17+
credential.sanitizePrompt::
18+
By default, user names and hosts that are shown as part of the
19+
password prompt are not allowed to contain control characters (they
20+
will be URL-encoded by default). Configure this setting to `false` to
21+
override that behavior.
22+
23+
credential.protectProtocol::
24+
By default, Carriage Return characters are not allowed in the protocol
25+
that is used when Git talks to a credential helper. This setting allows
26+
users to override this default.
27+
1728
credential.username::
1829
If no username is set for a network authentication, use this username
1930
by default. See credential.<context>.* below, and

compat/mingw.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ static const int delay[] = { 0, 1, 10, 20, 40 };
2727
void open_in_gdb(void)
2828
{
2929
static struct child_process cp = CHILD_PROCESS_INIT;
30-
extern char *_pgmptr;
3130

3231
strvec_pushl(&cp.args, "mintty", "gdb", NULL);
3332
strvec_pushf(&cp.args, "--pid=%d", getpid());

compat/regex/regcomp.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
868868
if (table_size > pat_len)
869869
break;
870870

871-
dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
871+
dfa->state_table = calloc (table_size, sizeof (struct re_state_table_entry));
872872
dfa->state_hash_mask = table_size - 1;
873873

874874
dfa->mb_cur_max = MB_CUR_MAX;
@@ -936,7 +936,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
936936
{
937937
int i, j, ch;
938938

939-
dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
939+
dfa->sb_char = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
940940
if (BE (dfa->sb_char == NULL, 0))
941941
return REG_ESPACE;
942942

@@ -3079,9 +3079,9 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
30793079
_NL_COLLATE_SYMB_EXTRAMB);
30803080
}
30813081
#endif
3082-
sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
3082+
sbcset = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
30833083
#ifdef RE_ENABLE_I18N
3084-
mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
3084+
mbcset = (re_charset_t *) calloc (1, sizeof (re_charset_t));
30853085
#endif /* RE_ENABLE_I18N */
30863086
#ifdef RE_ENABLE_I18N
30873087
if (BE (sbcset == NULL || mbcset == NULL, 0))
@@ -3626,9 +3626,9 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
36263626
re_token_t br_token;
36273627
bin_tree_t *tree;
36283628

3629-
sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
3629+
sbcset = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
36303630
#ifdef RE_ENABLE_I18N
3631-
mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
3631+
mbcset = (re_charset_t *) calloc (1, sizeof (re_charset_t));
36323632
#endif /* RE_ENABLE_I18N */
36333633

36343634
#ifdef RE_ENABLE_I18N

compat/regex/regex_internal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,7 +1628,7 @@ create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
16281628
reg_errcode_t err;
16291629
re_dfastate_t *newstate;
16301630

1631-
newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
1631+
newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
16321632
if (BE (newstate == NULL, 0))
16331633
return NULL;
16341634
err = re_node_set_init_copy (&newstate->nodes, nodes);
@@ -1678,7 +1678,7 @@ create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
16781678
reg_errcode_t err;
16791679
re_dfastate_t *newstate;
16801680

1681-
newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
1681+
newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
16821682
if (BE (newstate == NULL, 0))
16831683
return NULL;
16841684
err = re_node_set_init_copy (&newstate->nodes, nodes);

compat/regex/regexec.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,8 +2796,8 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
27962796
continue; /* No. */
27972797
if (sub_top->path == NULL)
27982798
{
2799-
sub_top->path = calloc (sizeof (state_array_t),
2800-
sl_str - sub_top->str_idx + 1);
2799+
sub_top->path = calloc (sl_str - sub_top->str_idx + 1,
2800+
sizeof (state_array_t));
28012801
if (sub_top->path == NULL)
28022802
return REG_ESPACE;
28032803
}
@@ -3361,7 +3361,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
33613361
if (ndests == 0)
33623362
{
33633363
state->trtable = (re_dfastate_t **)
3364-
calloc (sizeof (re_dfastate_t *), SBC_MAX);
3364+
calloc (SBC_MAX, sizeof (re_dfastate_t *));
33653365
return 1;
33663366
}
33673367
return 0;
@@ -3457,7 +3457,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
34573457
discern by looking at the character code: allocate a
34583458
256-entry transition table. */
34593459
trtable = state->trtable =
3460-
(re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
3460+
(re_dfastate_t **) calloc (SBC_MAX, sizeof (re_dfastate_t *));
34613461
if (BE (trtable == NULL, 0))
34623462
goto out_free;
34633463

@@ -3488,7 +3488,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
34883488
transition tables, one starting at trtable[0] and one
34893489
starting at trtable[SBC_MAX]. */
34903490
trtable = state->word_trtable =
3491-
(re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);
3491+
(re_dfastate_t **) calloc (2 * SBC_MAX, sizeof (re_dfastate_t *));
34923492
if (BE (trtable == NULL, 0))
34933493
goto out_free;
34943494

credential.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include "sigchain.h"
1111
#include "strbuf.h"
1212
#include "urlmatch.h"
13-
#include "git-compat-util.h"
13+
#include "environment.h"
1414

1515
void credential_init(struct credential *c)
1616
{
@@ -72,6 +72,10 @@ static int credential_config_callback(const char *var, const char *value,
7272
}
7373
else if (!strcmp(key, "usehttppath"))
7474
c->use_http_path = git_config_bool(var, value);
75+
else if (!strcmp(key, "sanitizeprompt"))
76+
c->sanitize_prompt = git_config_bool(var, value);
77+
else if (!strcmp(key, "protectprotocol"))
78+
c->protect_protocol = git_config_bool(var, value);
7579

7680
return 0;
7781
}
@@ -169,7 +173,8 @@ static void credential_format(struct credential *c, struct strbuf *out)
169173
strbuf_addch(out, '@');
170174
}
171175
if (c->host)
172-
strbuf_addstr(out, c->host);
176+
strbuf_add_percentencode(out, c->host,
177+
STRBUF_ENCODE_HOST_AND_PORT);
173178
if (c->path) {
174179
strbuf_addch(out, '/');
175180
strbuf_add_percentencode(out, c->path, 0);
@@ -183,7 +188,10 @@ static char *credential_ask_one(const char *what, struct credential *c,
183188
struct strbuf prompt = STRBUF_INIT;
184189
char *r;
185190

186-
credential_describe(c, &desc);
191+
if (c->sanitize_prompt)
192+
credential_format(c, &desc);
193+
else
194+
credential_describe(c, &desc);
187195
if (desc.len)
188196
strbuf_addf(&prompt, "%s for '%s': ", what, desc.buf);
189197
else
@@ -266,7 +274,8 @@ int credential_read(struct credential *c, FILE *fp)
266274
return 0;
267275
}
268276

269-
static void credential_write_item(FILE *fp, const char *key, const char *value,
277+
static void credential_write_item(const struct credential *c,
278+
FILE *fp, const char *key, const char *value,
270279
int required)
271280
{
272281
if (!value && required)
@@ -275,24 +284,28 @@ static void credential_write_item(FILE *fp, const char *key, const char *value,
275284
return;
276285
if (strchr(value, '\n'))
277286
die("credential value for %s contains newline", key);
287+
if (c->protect_protocol && strchr(value, '\r'))
288+
die("credential value for %s contains carriage return\n"
289+
"If this is intended, set `credential.protectProtocol=false`",
290+
key);
278291
fprintf(fp, "%s=%s\n", key, value);
279292
}
280293

281294
void credential_write(const struct credential *c, FILE *fp)
282295
{
283-
credential_write_item(fp, "protocol", c->protocol, 1);
284-
credential_write_item(fp, "host", c->host, 1);
285-
credential_write_item(fp, "path", c->path, 0);
286-
credential_write_item(fp, "username", c->username, 0);
287-
credential_write_item(fp, "password", c->password, 0);
288-
credential_write_item(fp, "oauth_refresh_token", c->oauth_refresh_token, 0);
296+
credential_write_item(c, fp, "protocol", c->protocol, 1);
297+
credential_write_item(c, fp, "host", c->host, 1);
298+
credential_write_item(c, fp, "path", c->path, 0);
299+
credential_write_item(c, fp, "username", c->username, 0);
300+
credential_write_item(c, fp, "password", c->password, 0);
301+
credential_write_item(c, fp, "oauth_refresh_token", c->oauth_refresh_token, 0);
289302
if (c->password_expiry_utc != TIME_MAX) {
290303
char *s = xstrfmt("%"PRItime, c->password_expiry_utc);
291-
credential_write_item(fp, "password_expiry_utc", s, 0);
304+
credential_write_item(c, fp, "password_expiry_utc", s, 0);
292305
free(s);
293306
}
294307
for (size_t i = 0; i < c->wwwauth_headers.nr; i++)
295-
credential_write_item(fp, "wwwauth[]", c->wwwauth_headers.v[i], 0);
308+
credential_write_item(c, fp, "wwwauth[]", c->wwwauth_headers.v[i], 0);
296309
}
297310

298311
static int run_credential_helper(struct credential *c,

credential.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ struct credential {
134134
configured:1,
135135
quit:1,
136136
use_http_path:1,
137-
username_from_proto:1;
137+
username_from_proto:1,
138+
sanitize_prompt:1,
139+
protect_protocol:1;
138140

139141
char *username;
140142
char *password;
@@ -149,6 +151,8 @@ struct credential {
149151
.helpers = STRING_LIST_INIT_DUP, \
150152
.password_expiry_utc = TIME_MAX, \
151153
.wwwauth_headers = STRVEC_INIT, \
154+
.sanitize_prompt = 1, \
155+
.protect_protocol = 1, \
152156
}
153157

154158
/* Initialize a credential structure, setting all fields to empty. */

strbuf.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,9 @@ void strbuf_add_percentencode(struct strbuf *dst, const char *src, int flags)
500500
unsigned char ch = src[i];
501501
if (ch <= 0x1F || ch >= 0x7F ||
502502
(ch == '/' && (flags & STRBUF_ENCODE_SLASH)) ||
503-
strchr(URL_UNSAFE_CHARS, ch))
503+
((flags & STRBUF_ENCODE_HOST_AND_PORT) ?
504+
!isalnum(ch) && !strchr("-.:[]", ch) :
505+
!!strchr(URL_UNSAFE_CHARS, ch)))
504506
strbuf_addf(dst, "%%%02X", (unsigned char)ch);
505507
else
506508
strbuf_addch(dst, ch);

0 commit comments

Comments
 (0)