Merge branch 'jk/c23-const-preserving-fixes-more'

Further work to adjust the codebase for C23 that changes functions
like strchr() that discarded constness when they return a pointer into
a const string to preserve constness.

* jk/c23-const-preserving-fixes-more:
  git-compat-util: fix CONST_OUTPARAM typo and indentation
  refs/files-backend: drop const to fix strchr() warning
  http: drop const to fix strstr() warning
  range-diff: drop const to fix strstr() warnings
  pkt-line: make packet_reader.line non-const
  skip_prefix(): check const match between in and out params
  pseudo-merge: fix disk reads from find_pseudo_merge()
  find_last_dir_sep(): convert inline function to macro
  run-command: explicitly cast away constness when assigning to void
  pager: explicitly cast away strchr() constness
  transport-helper: drop const to fix strchr() warnings
  http: add const to fix strchr() warnings
  convert: add const to fix strchr() warnings
maint
Junio C Hamano 2026-04-09 11:21:59 -07:00
commit 3eabc358a9
15 changed files with 74 additions and 46 deletions

View File

@ -1029,8 +1029,8 @@ static int read_proc_receive_report(struct packet_reader *reader,

for (;;) {
struct object_id old_oid, new_oid;
const char *head;
const char *refname;
char *head;
char *refname;
char *p;
enum packet_read_status status;

@ -1054,7 +1054,8 @@ static int read_proc_receive_report(struct packet_reader *reader,
}
*p++ = '\0';
if (!strcmp(head, "option")) {
const char *key, *val;
char *key;
const char *val;

if (!hint || !(report || new_report)) {
if (!once++)

View File

@ -1168,7 +1168,8 @@ static int ident_to_worktree(const char *src, size_t len,
struct strbuf *buf, int ident)
{
struct object_id oid;
char *to_free = NULL, *dollar, *spc;
char *to_free = NULL;
const char *dollar, *spc;
int cnt;

if (!ident)

View File

@ -335,11 +335,7 @@ static inline int is_path_owned_by_current_uid(const char *path,
#endif

#ifndef find_last_dir_sep
static inline char *git_find_last_dir_sep(const char *path)
{
return strrchr(path, '/');
}
#define find_last_dir_sep git_find_last_dir_sep
#define find_last_dir_sep(path) strrchr((path), '/')
#endif

#ifndef has_dir_sep
@ -467,6 +463,21 @@ void set_warn_routine(report_fn routine);
report_fn get_warn_routine(void);
void set_die_is_recursing_routine(int (*routine)(void));

/*
* Check that an out-parameter is "at least as const as" a matching
* in-parameter. For example, skip_prefix() will return "out" that is a subset
* of "str". So:
*
* const str, const out: ok
* non-const str, const out: ok
* non-const str, non-const out: ok
* const str, non-const out: compile error
*
* See the skip_prefix macro below for an example of use.
*/
#define CONST_OUTPARAM(in, out) \
((const char **)(0 ? ((*(out) = (in)),(out)) : (out)))

/*
* If the string "str" begins with the string found in "prefix", return true.
* The "out" parameter is set to "str + strlen(prefix)" (i.e., to the point in
@ -483,7 +494,9 @@ void set_die_is_recursing_routine(int (*routine)(void));
* [skip prefix if present, otherwise use whole string]
* skip_prefix(name, "refs/heads/", &name);
*/
static inline bool skip_prefix(const char *str, const char *prefix,
#define skip_prefix(str, prefix, out) \
skip_prefix_impl((str), (prefix), CONST_OUTPARAM((str), (out)))
static inline bool skip_prefix_impl(const char *str, const char *prefix,
const char **out)
{
do {
@ -889,7 +902,9 @@ static inline size_t xsize_t(off_t len)
* is done via tolower(), so it is strictly ASCII (no multi-byte characters or
* locale-specific conversions).
*/
static inline bool skip_iprefix(const char *str, const char *prefix,
#define skip_iprefix(str, prefix, out) \
skip_iprefix_impl((str), (prefix), CONST_OUTPARAM((str), (out)))
static inline bool skip_iprefix_impl(const char *str, const char *prefix,
const char **out)
{
do {

2
hex.c
View File

@ -54,7 +54,7 @@ int get_oid_hex(const char *hex, struct object_id *oid)
return get_oid_hex_algop(hex, oid, the_hash_algo);
}

int parse_oid_hex_algop(const char *hex, struct object_id *oid,
int parse_oid_hex_algop_impl(const char *hex, struct object_id *oid,
const char **end,
const struct git_hash_algo *algop)
{

4
hex.h
View File

@ -40,7 +40,9 @@ char *oid_to_hex(const struct object_id *oid); /* same static buffer */
* other invalid character. end is only updated on success; otherwise, it is
* unmodified.
*/
int parse_oid_hex_algop(const char *hex, struct object_id *oid, const char **end,
#define parse_oid_hex_algop(hex, oid, end, algo) \
parse_oid_hex_algop_impl((hex), (oid), CONST_OUTPARAM((hex), (end)), (algo))
int parse_oid_hex_algop_impl(const char *hex, struct object_id *oid, const char **end,
const struct git_hash_algo *algo);

/*

View File

@ -99,7 +99,7 @@ static struct object_list *objects;

struct repo {
char *url;
char *path;
const char *path;
int path_len;
int has_info_refs;
int can_update_info_refs;

4
http.c
View File

@ -748,7 +748,7 @@ static int has_proxy_cert_password(void)
static int redact_sensitive_header(struct strbuf *header, size_t offset)
{
int ret = 0;
const char *sensitive_header;
char *sensitive_header;

if (trace_curl_redact &&
(skip_iprefix(header->buf + offset, "Authorization:", &sensitive_header) ||
@ -765,7 +765,7 @@ static int redact_sensitive_header(struct strbuf *header, size_t offset)
} else if (trace_curl_redact &&
skip_iprefix(header->buf + offset, "Cookie:", &sensitive_header)) {
struct strbuf redacted_header = STRBUF_INIT;
const char *cookie;
char *cookie;

while (isspace(*sensitive_header))
sensitive_header++;

View File

@ -108,10 +108,11 @@ const char *git_pager(struct repository *r, int stdout_is_tty)

static void setup_pager_env(struct strvec *env)
{
const char **argv;
char **argv;
int i;
char *pager_env = xstrdup(PAGER_ENV);
int n = split_cmdline(pager_env, &argv);
/* split_cmdline splits in place, so we know the result is writable */
int n = split_cmdline(pager_env, (const char ***)&argv);

if (n < 0)
die("malformed build-time PAGER_ENV: %s",

View File

@ -184,7 +184,7 @@ struct packet_reader {
int pktlen;

/* the last line read */
const char *line;
char *line;

/* indicates if a line has been peeked */
int line_peeked;

View File

@ -638,14 +638,21 @@ static int pseudo_merge_commit_cmp(const void *va, const void *vb)
return 0;
}

static struct pseudo_merge_commit *find_pseudo_merge(const struct pseudo_merge_map *pm,
uint32_t pos)
static int find_pseudo_merge(const struct pseudo_merge_map *pm, uint32_t pos,
struct pseudo_merge_commit *out)
{
if (!pm->commits_nr)
return NULL;
const unsigned char *at;

return bsearch(&pos, pm->commits, pm->commits_nr,
if (!pm->commits_nr)
return 0;

at = bsearch(&pos, pm->commits, pm->commits_nr,
PSEUDO_MERGE_COMMIT_RAWSZ, pseudo_merge_commit_cmp);
if (!at)
return 0;

read_pseudo_merge_commit_at(out, at);
return 1;
}

int apply_pseudo_merges_for_commit(const struct pseudo_merge_map *pm,
@ -653,16 +660,15 @@ int apply_pseudo_merges_for_commit(const struct pseudo_merge_map *pm,
struct commit *commit, uint32_t commit_pos)
{
struct pseudo_merge *merge;
struct pseudo_merge_commit *merge_commit;
struct pseudo_merge_commit merge_commit;
int ret = 0;

merge_commit = find_pseudo_merge(pm, commit_pos);
if (!merge_commit)
if (!find_pseudo_merge(pm, commit_pos, &merge_commit))
return 0;

if (merge_commit->pseudo_merge_ofs & ((uint64_t)1<<63)) {
if (merge_commit.pseudo_merge_ofs & ((uint64_t)1<<63)) {
struct pseudo_merge_commit_ext ext = { 0 };
off_t ofs = merge_commit->pseudo_merge_ofs & ~((uint64_t)1<<63);
off_t ofs = merge_commit.pseudo_merge_ofs & ~((uint64_t)1<<63);
uint32_t i;

if (pseudo_merge_ext_at(pm, &ext, ofs) < -1) {
@ -673,11 +679,11 @@ int apply_pseudo_merges_for_commit(const struct pseudo_merge_map *pm,
}

for (i = 0; i < ext.nr; i++) {
if (nth_pseudo_merge_ext(pm, &ext, merge_commit, i) < 0)
if (nth_pseudo_merge_ext(pm, &ext, &merge_commit, i) < 0)
return ret;

merge = pseudo_merge_at(pm, &commit->object.oid,
merge_commit->pseudo_merge_ofs);
merge_commit.pseudo_merge_ofs);

if (!merge)
return ret;
@ -687,7 +693,7 @@ int apply_pseudo_merges_for_commit(const struct pseudo_merge_map *pm,
}
} else {
merge = pseudo_merge_at(pm, &commit->object.oid,
merge_commit->pseudo_merge_ofs);
merge_commit.pseudo_merge_ofs);

if (!merge)
return ret;

View File

@ -88,7 +88,7 @@ static int read_patches(const char *range, struct string_list *list,
line = contents.buf;
size = contents.len;
for (; size > 0; size -= len, line += len) {
const char *p;
char *p;
char *eol;

eol = memchr(line, '\n', size);

View File

@ -2190,7 +2190,7 @@ static int show_one_reflog_ent(struct files_ref_store *refs,
char *email_end, *message;
timestamp_t timestamp;
int tz;
const char *p = sb->buf;
char *p = sb->buf;

/* old SP new SP name <email> SP time TAB msg LF */
if (!sb->len || sb->buf[sb->len - 1] != '\n' ||

View File

@ -604,11 +604,11 @@ static void trace_add_env(struct strbuf *dst, const char *const *deltaenv)
/* Last one wins, see run-command.c:prep_childenv() for context */
for (e = deltaenv; e && *e; e++) {
struct strbuf key = STRBUF_INIT;
char *equals = strchr(*e, '=');
const char *equals = strchr(*e, '=');

if (equals) {
strbuf_add(&key, *e, equals - *e);
string_list_insert(&envs, key.buf)->util = equals + 1;
string_list_insert(&envs, key.buf)->util = (void *)(equals + 1);
} else {
string_list_insert(&envs, *e)->util = NULL;
}

View File

@ -175,8 +175,8 @@ static int receive_status(struct repository *r,
ret = receive_unpack_status(reader);
while (1) {
struct object_id old_oid, new_oid;
const char *head;
const char *refname;
char *head;
char *refname;
char *p;
if (packet_reader_read(reader) != PACKET_READ_NORMAL)
break;
@ -190,7 +190,8 @@ static int receive_status(struct repository *r,
*p++ = '\0';

if (!strcmp(head, "option")) {
const char *key, *val;
char *key;
const char *val;

if (!hint || !(report || new_report)) {
if (!once++)

View File

@ -783,7 +783,8 @@ static int push_update_ref_status(struct strbuf *buf,

if (starts_with(buf->buf, "option ")) {
struct object_id old_oid, new_oid;
const char *key, *val;
char *key;
const char *val;
char *p;

if (!state->hint || !(state->report || state->new_report))